当前位置: 首页 > news >正文

详细解读ts中的函数重载

一、函数重载的核心概念

有些函数可以接受不同类型或不同个数的参数,并且根据参数的不同,会有不同的函数行为。这种根据参数类型不同,执行不同逻辑的行为,称为函数重载(function overload)。

    简单示例:

    reverse('abc') // 'cba'
    reverse([1, 2, 3]) // [3, 2, 1]

    上面示例中,函数reverse()可以将参数颠倒输出。参数可以是字符串,也可以是数组。

    这意味着,该函数内部有处理字符串和数组的两套逻辑,根据参数类型的不同,分别执行对应的逻辑。这就叫“函数重载”。

    展开来说,其核心由两部分构成:

    1. 重载签名(Overload Signatures):定义函数的不同调用形式(参数类型/数量及返回类型),不包含实现。
    2. 实现签名(Implementation Signature):包含实际逻辑的函数体,需兼容所有重载签名。

    示例:

    // 重载签名
    function reverse(str:string):string;
    function reverse(arr:any[]):any[];
    // 实现签名
    function reverse(
      stringOrArray:string|any[]
    ):string|any[] {
      if (typeof stringOrArray === 'string')
        return stringOrArray.split('').reverse().join('');
      else
        return stringOrArray.slice().reverse();
    }

    上面示例中,前两行类型声明列举了重载的各种情况。第三行是函数本身的类型声明,它必须与前面已有的重载声明兼容

    二、函数重载的核心规则

    1. 签名顺序a:重载签名需在实现签名之前声明,实现签名参数类型需覆盖所有重载可能性(如联合类型或any),b:重载重载签名函数实现签名之间,不能有其他代码,否则报错。c:重载声明的排序很重要,因为 TypeScript 是按照顺序进行检查的,一旦发现符合某个类型声明,就不再往下检查了,所以类型最宽的声明应该放在最后面,防止覆盖其他类型声明。
      function f(x:any):number;
      function f(x:string): 0|1;
      function f(x:any):any {
        // ...
      }
      const a:0|1 = f('hi'); // 报错
      
      // 该例子,第一行类型声明x:any范围最宽,导致函数f()的调用都会匹配这行声明,无法匹配第二行类型声明,所以最后一行调用就报错了,因为等号两侧类型不匹配,左侧类型是0|1,右侧类型是number。这个函数重载的正确顺序是,第二行类型声明放到第一行的位置。
    2. 返回类型匹配:各重载签名的返回类型需独立明确,实现签名需兼容所有可能返回类型 。函数重载的每个类型声明之间,以及类型声明与函数实现的类型之间,不能有冲突。
      // 报错
      function fn(x:boolean):void;
      function fn(x:string):void;
      function fn(x:number|string) {
        console.log(x);
      }
    3. 参数类型处理:实现签名通过类型守卫(如typeofinstanceof)区分参数类型逻辑 。
       

    三、典型应用场景

    1. 参数类型决定返回类型
    // 根据参数类型返回不同结构
    function add(
      x:number,
      y:number
    ):number;
    function add(
      x:any[],
      y:any[]
    ):any[];
    function add(
      x:number|any[],
      y:number|any[]
    ):number|any[] {
      if (typeof x === 'number' && typeof y === 'number') {
        return x + y;
      } else if (Array.isArray(x) && Array.isArray(y)) {
        return [...x, ...y];
      }
      throw new Error('wrong parameters');
    }

    上面示例中,函数add()内部使用if代码块,分别处理参数的两种情况。

    • 调用提示:IDE会根据参数类型自动推断返回类型,提升开发体验 。
       

    虽然函数的具体实现里面,有完整的类型声明。但是,函数实际调用的类型,以前面的类型声明为准。比如,上例的函数实现,参数类型和返回值类型都是number|any[],但不意味着参数类型为number时返回值类型为any[]。 

    2. 参数数量不同时的行为差异
    // 参数数量不同时的重载
    function createDate(timestamp: number): Date;
    function createDate(year: number, month: number, day: number): Date;
    function createDate(a: number, b?: number, c?: number): Date {
      if (b !== undefined) return new Date(a, b, c);
      return new Date(a);
    }
    • 参数校验:调用createDate(2023, 5, 20)会匹配第二个签名 。
       
    3. 面向对象方法重载 
    class Calculator {
      add(a: number, b: number): number;
      add(a: string, b: string): string;
      add(a: any, b: any): any {
        return a + b;
      }
    }

     4.函数重载也可以用来精确描述函数参数与返回值之间的对应关系。

    function createElement(
      tag:'a'
    ):HTMLAnchorElement;
    function createElement(
      tag:'canvas'
    ):HTMLCanvasElement;
    function createElement(
      tag:'table'
    ):HTMLTableElement;
    function createElement(
      tag:string
    ):HTMLElement {
      // ...
    }
    
    
    // 上述例子的函数重载,也可以用对象表示。
    type CreateElement = {
      (tag:'a'): HTMLAnchorElement;
      (tag:'canvas'): HTMLCanvasElement;
      (tag:'table'): HTMLTableElement;
      (tag:string): HTMLElement;
    }

     上面示例中,函数重载精确描述了参数tag的三个值,所对应的不同的函数返回值。

    四、函数重载与联合类型的取舍

    场景推荐方案原因
    参数类型影响返回值类型函数重载

    明确返回值类型关联(如string返回stringnumber返回number) 

    参数类型不影响返回值联合类型简化代码结构(如`function len(x: string
    需要精确的IDE提示函数重载

    根据参数类型动态提示返回值类型 

    五、高级技巧与注意事项

    1. 泛型重载

      function merge<T>(arr1: T[], arr2: T[]): T[];
      function merge<T, U>(arr1: T[], arr2: U[]): (T | U)[];
      function merge(arr1: any[], arr2: any[]): any[] {
        return [...arr1, ...arr2];
      }
      • 支持泛型参数,处理不同类型数组的合并 。
         
    2. 构造器重载模拟

      class Square {
        constructor(width: number, height: number);
        constructor(config: { width: number; height: number });
        constructor(config: any, height?: number) {
          // 实现逻辑
        }
      }
      • 通过联合类型模拟构造函数重载 。
         
    3. 避免常见错误

    • 实现签名不兼容:确保实现参数覆盖所有重载可能性。
    • 过度使用重载:优先用联合类型简化代码,避免维护成本增加 ,如:
      // 写法一
      function len(s:string):number;
      function len(arr:any[]):number;
      function len(x:any):number {
        return x.length;
      }
      // 写法二
      function len(x:any[]|string):number {
        return x.length;
      }
      上面示例中,写法二使用联合类型,要比写法一的函数重载简单很多。

    相关文章:

  1. LiT and Lean: Distilling Listwise Rerankers intoEncoder-Decoder Models
  2. 佳能imageRUNNER 2935复印机调整休眠时间方法
  3. Meta LLaMA 4:对抗 GPT-4o 与 Claude 的开源王牌
  4. 【教学类-102-05】蛋糕剪纸图案(留白边、沿线剪)04——Python白色(255)图片转为透明png再制作“点状边框和虚线边框”
  5. BGP路由协议之属性1
  6. 手搓多模态-06 数据预处理
  7. 硬件设计中串联电阻的作用、阻值范围及选取方法详解
  8. 如何正确使用 `apiStore` 进行 API 管理
  9. 16-产品经理-需求的评审
  10. Nmap全脚本使用指南!NSE脚本全详细教程!Kali Linux教程!(七)
  11. 35.[前端开发-JavaScript基础]Day12-for循环中变量-华为商城-商品列表-轮播图
  12. 心律异常检测
  13. 以UE5第三方插件库为基础,编写自己的第三方库插件,并且能够在运行时复制.dll
  14. 【内网渗透】Linux上线CS学习-CrossC2插件
  15. Hybrid 架构的概念,以及如何优化Hybrid 通信方案,提升页面加载速度和渲染性能
  16. 【c++深入系列】:类和对象详解(下)
  17. SpringMVC的数据响应
  18. 13-Leveldb快照原理及其实现
  19. 嵌入式工程师多线程编程(四)裸机编程实现多任务调度
  20. 2026考研数学张宇武忠祥复习视频课,高数基础班+讲义PDF
  21. 视频网站做短视频/做一个企业网站需要多少钱
  22. 沈阳做企业网站的公司/2023年6月份疫情严重吗
  23. 旅行社网站建设方案/有创意的营销案例
  24. wordpress音乐主题musik汉化/新乡seo优化
  25. 网站中的横幅怎么做/郑州百度推广代理公司
  26. 外网下载/网站搜索引擎优化的基本内容