Reputation: 1556
I have a method to filter a list based on some fileds and sometimes I can have an extra pageNumber and limit for which to filter my list and get only a limited number of entries.
This is what I have in code:
public getByFilter(
fitler?: { [P in keyof T]?: T[P] } & { pageNumber?: number; limit?: number }
): Observable<IPagedResult<T>> { // code to filter }
and using this method
.getByFilter({ ...filters })
.subscribe((response: IPagedResult<MyClass>) => {
// do something
});
Can my method have a return type of
Observable<T[]>
if my filters object does not contain pageNumber and limit?
and then to use it like
.getByFilter({ ...filters })
.subscribe((response: MyClass[]) => {
// do something
});
Upvotes: 1
Views: 40
Reputation: 6994
This is currently only possible with some hacky casting on the implementation side, the issue is being tracked however (#24929, #22735, #22596) and the maintainers declared it as a design limition.
The solution is to define the filter
parameter as generic parameter like this:
type BasicFilter<T> = { [P in keyof T]?: T[P] };
type PaginationFilter<T> = BasicFilter<T> & { pageNumber: number, limit: number };
type Filter<T> = BasicFilter<T> | PaginationFilter<T>;
public getByFilter<F extends Filter<T>>(filter: F): F extends PaginationFilter<T> ? Observable<IPagedResult<T>> : Observable<T> {
/**/
}
the return type is being infered based on whether input is a pagination filter or basic filter.
This works as expected on the call side:
const paged = new Observable<Test>({foo: 1, bar: ''}).getByFilter({
pageNumber: 2,
limit: 2,
});
// paged as type: Observable<IPagedResult<Test>>
const raw = new Observable<Test>({foo: 1, bar: ''}).getByFilter({});
// raw as type: Observable<Test>
On the implementation side you need a asseration as any
like this (the mentioned issue which is being tracked on GitHub):
if ('pageNumber' in filter && 'limit' in filter) {
return new Observable<IPagedResult<T>>({
data: this.value,
}) as any;
}
return this as any;
A full example can be found here in this playground.
Upvotes: 1