跳到主要内容

重载

2023年01月12日
柏拉文
越努力,越幸运

一、优势

  1. 结构分明,让代码可读性,可维护性提升许多,而且代码更漂亮
  2. 各司其职,自动提示方法和属性,每个重载函数完成各自的功能,输出取值时不用强制转换就能出动自动提示,从而提高开发效率。
  3. 更利于功能扩展

二、规则

函数重载 一组具有相同的名字,不同的参数列表、不同的返回值的函数。

函数签名 函数签名 = 函数名称 + 函数参数个数 + 函数参数类型 + 返回值类型 四者合成。在TypeScript中,包含了实现签名重载签名实现签名是一种函数签名,重载签名也是一种函数签名。

完整的函数重载定义规则如下:

  • 规则1: 由一个实现签名 + 一个或多个重载签名合成
  • 规则2: 外部调用函数重载定义的函数时,只能调用重载签名,不能调用实现签名。这是因为实现签名下的函数体是给重载签名编写的,实现签名只是在定义时起到了统领所有重载签名的作用,在执行调用时就看不到实现签名了。
  • 规则3: 调用重载函数时,会根据传递的参数来判断你调用的是哪一个函数
  • 规则4: 只有一个函数体,只有实现签名配备了函数体,所有的重载签名都只有签名,没有配备函数体。
  • 规则5: 关于参数类型规则完整总结如下:
    • 无论重载签名由几个参数、参数是何种类型,实现签名都可以是一个无参函数签名
    • 实现签名参数个数可以少于重载签名的参数个数,但实现签名如果准备包含重载签名的某个位置的参数,那实现签名就必须兼容所有重载签名该位置的参数类型
  • 规则6: 关于重载签名和实现签名的返回值类型规则完整总结如下:
    • 必须给重载签名提供返回值类型,TypeScript 无法默认推导
    • 提供给重载签名的返回值类型不一定为其执行时的真实返回值类型,可以为重载签名提供真实返回值类型,也可以提供 void 或 unknown 或 any 类型。如果重载签名的返回值类型是 void 或 unknown 或 any 类型,那么将由实现签名来决定重载签名执行时的真实返回值类型。当然为了调用时能有自动提示+可读性更好+避免可能出现了类型强制转换,强烈建议为重载签名提供真实返回值类型。
    • 不管重载签名返回值类型时何种类型,实现签名都可以返回 any 类型 或者 unknown 类型,当然一般我们两者都不选择,让 TypeScript 默认为实现签名自动推导返回值类型

三、理解

  • 通过函数重载实现消息推送功能

    使用函数重载,实现消息推送
    type MessageType = "image" | "audio" | string;
    type Message = {
    id:number;
    type:MessageType;
    sendMessage:string;
    }
    let messages:Message[] = [
    {
    id:1,
    type:'image',
    sendMessage: '哈哈哈'
    },
    {
    id:2,
    type:'image',
    sendMessage: '哈哈哈'
    },
    {
    id:3,
    type:'image',
    sendMessage: '哈哈哈'
    },
    {
    id:4,
    type:'audio',
    sendMessage: '嘻嘻嘻'
    },
    {
    id:5,
    type:'呵呵呵',
    sendMessage: '呵呵呵'
    },
    ]

    function getMessage(value:number,property:string):Message|undefined;
    function getMessage(value:MessageType,end:number):Message[];
    function getMessage(value1:number|MessageType,value2:number|string):Message|Message[]|undefined{
    if(typeof value1 === "number" && typeof value2 === 'string'){
    return messages.find(item=>{
    return item.id === value1;
    });
    }else if(typeof value1 !== "number" && typeof value2 === 'number'){
    return messages.filter(item=>{
    return value1 === item.type;
    }).slice(0,value2);
    }
    }

    console.log(getMessage(3,'sendMessage'));
    console.log(getMessage('image',2));

    export {}