Reputation: 9453
I'm trying to make a function overloading for the search()
function. This method must have different search actions.
search(key: string): IPagination<Employee[]>;
BasicFilter
type:
search(x: BasicFilter): IPagination<Employee[]>;
PaginatedFilter
type:
search(y: PaginatedFilter): IPagination<Employee[]>;
How can i check the type of this interfaces in search(args: any): any;
method?
Tried doing the following:
if (typeof args === BasicFilter) {
console.log('searched with basic filter arguments');
}
TS message: 'BasicFilter' only refers to a type, but is being used as a value here.
Error message: BasicFilter is not defined
Here are the following codes:
The Interfaces
interface PageData {
pageIndex: number;
pageSize: number;
}
interface Employee {
id: number;
name: string;
}
interface BasicFilter {
key: string;
is_archived: boolean;
}
interface PaginatedFilter {
key: string;
is_archived: boolean;
page: PageData;
}
interface IPagination<T> {
length: number;
list: T;
}
The Class
class Service {
constructor(public name) {}
search(x: BasicFilter): IPagination<Employee[]>;
search(y: PaginatedFilter): IPagination<Employee[]>;
search(key: string): IPagination<Employee[]>;
search(args: any): any {
if (typeof args === 'string') {
console.log('searched with keyword only');
}
if (typeof args === 'object') {
console.log('searched with object arguments');
}
}
}
Usage
const service = new Service('Serbisyo publiko');
service.search({ key: 'some key', is_archived: false });
const default_page: PageData = { pageIndex: 0, pageSize: 15 };
service.search({ key: 'some queries', is_archived: true, page: default_page });
service.search('filtering data..');
The Output
searched with object arguments
searched with object arguments
searched with keyword only
Upvotes: 1
Views: 74
Reputation: 250366
Since interfaces don't exist at runtime you can't type guard them them with typeof
(which works for primitive types) or instanceof
(which would work for classes). You can use an in
type guard which discriminates a union based on the existence of a fields. Also I would use a union of the possible parameter types for the implementation signature so type guards work correctly and you have full type safety. In your case the page
field appers to be a good candidate for this:
search(x: BasicFilter): IPagination<Employee[]>;
search(y: PaginatedFilter): IPagination<Employee[]>;
search(key: string): IPagination<Employee[]>;
search(args: BasicFilter | PaginatedFilter | string): any {
if (typeof args === 'string') {
console.log('searched with keyword only');
args // is typed to string here
}
else if ('page' in args) {
console.log('searched with object arguments');
args // is typed to PaginatedFilter here
}else {
args // is typed to BasicFilter here
}
}
Note Order of type guards matters, you have to remove the string from the union first as the in
type guard will only work if all types in the union are objects.
Upvotes: 2
Reputation: 1
From your question it can be seen that currently there are three search possibilities exposed through different interface like Basic Filter, Paginated Filter etc and also string. Tommorow it may so happen that you may need to come up with another interface that has diferent search filter.
To provide extensibilty and a comon searching terminolgy that helps you achieve OCP, please have all your interfaces derive from another dummy interface like IFilterCriteria. This means Basic Filter, Paginated Filter will now derive from IFilterCriteria. Also to provide for strign based search creater another interface called StringFilter will also derive from IFilterCriteria.
IFilterCriteria interface will be defined as:
interface IFilterCriteria {
}
This means it do not hold any state. It is just a marker interface
BasicFilter interface now will be defined as
interface BasicFilter extends IFilterCriteria {
key: string;
is_archived: boolean;
}
Similarly we can have modified definition of
interface PaginatedFilter extends IFilterCriteria {
key: string;
is_archived: boolean;
page: PageData;
}
Thus this provides common ground all current and future filtering possibilities.
And now the search function becomes more type safe and its signature will be:
search(args: IFilterCriteria): any;
Since now search takes this IFilterCriteria interface as parameter it can safely be type-casted and checked within function body
Upvotes: 0