带接口参数的函数重载

时间:2018-06-20 06:20:40

标签: typescript

我正在尝试使SELECT_CATALOG_ROLE函数重载。此方法必须具有不同的搜索操作。

  1. 仅搜索字符串类型。
    • search()
  2. 使用search(key: string): IPagination<Employee[]>;类型的搜索:
    • BasicFilter
  3. 使用search(x: BasicFilter): IPagination<Employee[]>;类型的搜索:
    • PaginatedFilter

如何使用search(y: PaginatedFilter): IPagination<Employee[]>;方法检查此接口的类型?

尝试执行以下操作:

search(args: any): any;

TS消息:“ BasicFilter”仅引用一种类型,但在此处用作值。

错误消息:未定义BasicFilter


以下是以下代码:

界面

  if (typeof args === BasicFilter) {
    console.log('searched with basic filter arguments');
  }

班级

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;
}

用法

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');
      }

    }

}

输出

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..');

DEMO

2 个答案:

答案 0 :(得分:2)

由于接口在运行时不存在,因此无法使用typeof(适用于原始类型)或instanceof(适用于类)进行类型保护。您可以使用in类型防护,根据字段的存在来区分并集。另外,我会为实现签名使用可能的参数类型的并集,以便类型防护程序正常工作,并且您具有完全的类型安全性。在您的情况下,page字段很适合作为此选项:

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
    }
}

注意类型保护的顺序很重要,您必须首先从联合中删除字符串,因为in类型保护仅在联合中的所有类型都是对象时才起作用。

答案 1 :(得分:0)

从您的问题中可以看出,当前通过不同的界面(例如基本过滤器,分页过滤器等)和字符串显示了三种搜索可能性。 Tommorow可能会发生这种情况,您可能需要提出另一个具有不同搜索过滤器的界面。

要提供可扩展性和有助于您实现OCP的通用搜索术语,请让您的所有接口都来自另一个虚拟接口(如IFilterCriteria)。这意味着基本过滤器,分页过滤器现在将从IFilterCriteria派生。另外,为了提供基于Strign的搜索创建器,还将从IFilterCriteria派生另一个名为StringFilter的接口。

IFilterCriteria接口将定义为:

interface IFilterCriteria {
}

这意味着它不处于任何状态。这只是一个标记界面

BasicFilter接口现在将定义为

interface BasicFilter extends IFilterCriteria {
    key: string;
    is_archived: boolean;
}

类似地,我们可以修改

的定义
interface PaginatedFilter extends IFilterCriteria {
    key: string;
    is_archived: boolean;
    page: PageData;
}

因此,这为所有当前和将来的过滤可能性提供了共同点。

现在搜索功能变得更加安全,其签名将为:

search(args: IFilterCriteria): any;

由于现在搜索将这个IFilterCriteria接口作为参数,因此可以安全地在函数体内进行类型转换和检查