美文网首页
TS 函数重载

TS 函数重载

作者: NowhereToRun | 来源:发表于2018-10-21 17:13 被阅读107次

    函数重载

    这个概念是在一些强类型语言中才有的,在JS中依据不同参数类型或参数个数执行一些不同函数体的实现很常见,依托于TypeScript,就会有需要用到这种声明的地方。

    关于函数重载,必须要把精确的定义放在前面,最后函数实现时,需要使用 |操作符或者?操作符,把所有可能的输入类型全部包含进去,以具体实现。如下例子1 和 例子3

    例子1
    例如我们有一个add函数,它可以接收string类型的参数进行拼接,也可以接收number类型的参数进行相加。

    // 上边是声明
    function add (arg1: string, arg2: string): string
    function add (arg1: number, arg2: number): number
    // 因为我们在下边有具体函数的实现,所以这里并不需要添加 declare 关键字
    
    // 下边是实现
    function add (arg1: string | number, arg2: string | number) {
      // 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 arg1 + arg2
      if (typeof arg1 === 'string' && typeof arg2 === 'string') {
        return arg1 + arg2
      } else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
        return arg1 + arg2
      }
    }
    

    TypeScript 中的函数重载也只是多个函数的声明,具体的逻辑还需要自己去写,他并不会真的将你的多个重名 function 的函数体进行合并

    考虑如下 例子2

    interface User {
      name: string;
      age: number;
    }
    
    declare function test(para: User | number, flag?: boolean): number;
    

    在这个 test 函数里,我们的本意可能是当传入参数 para 是 User 时,不传 flag,当传入 para 是 number 时,传入 flag。TypeScript 并不知道这些,当你传入 para 为 User 时,flag 同样允许你传入:

    const user = {
      name: 'Jack',
      age: 666
    }
    
    // 没有报错,但是与想法违背
    const res = test(user, false);
    

    使用函数重载能帮助我们实现:

    interface User {
      name: string;
      age: number;
    }
    
    declare function test(para: User): number;
    declare function test(para: number, flag: boolean): number;
    
    const user = {
      name: 'Jack',
      age: 666
    };
    
    // bingo
    // Error: 参数不匹配
    const res = test(user, false);
    

    实际项目中,你可能要多写几步,如在 class 中:

    interface User {
      name: string;
      age: number;
    }
    
    const user = {
      name: 'Jack',
      age: 123
    };
    
    class SomeClass {
    
      /**
       * 注释 1
       */
      public test(para: User): number;
      /**
       * 注释 2
       */
      public test(para: number, flag: boolean): number;
      public test(para: User | number, flag?: boolean): number {
        // 具体实现
        return 11;
      }
    }
    
    const someClass = new SomeClass();
    
    
    // ok
    someClass.test(user);
    someClass.test(123, false);
    
    // Error
    someClass.test(123);
    someClass.test(user, false);
    

    一些不需要函数重载的场景(并不绝对,如上例子2)

    函数重载的意义在于能够让你知道传入不同的参数得到不同的结果,如果传入的参数不同,但是得到的结果(类型)却相同,那么这里就不要使用函数重载(没有意义)。
    如果函数的返回值类型相同,那么就不需要使用函数重载

    function func (a: number): number
    function func (a: number, b: number): number
    
    // 像这样的是参数个数的区别,我们可以使用可选参数来代替函数重载的定义
    
    function func (a: number, b?: number): number
    
    // 注意第二个参数在类型前边多了一个`?`
    
    // 亦或是一些参数类型的区别导致的
    function func (a: number): number
    function func (a: string): number
    
    // 这时我们应该使用联合类型来代替函数重载
    function func (a: number | string): number
    

    参考资料

    如何编写 Typescript 声明文件
    巧用 TypeScript (一)

    相关文章

      网友评论

          本文标题:TS 函数重载

          本文链接:https://www.haomeiwen.com/subject/fvibzftx.html