一,函数重载
在javascript中,我们编写的函数经常会判断传入的参数类型和个数,从而返回不同的结果。
比如这样:
function ts_pickCard(x) {
if (typeof x == 'object') {
return 1
}else if (typeof x == 'string') {
return {
result: 1
}
}
}
当传入字符串时,返回一个对象,反之,传入一个对象时,则会返回字符串。在typescript中可以使用函数重载来进行类型推断(根据不同的传参类型和个数,return不同的返回值)。
TS 函数重载定义:一组具有相同名字,不同参数列表的和返回值无关的函数
下面是函数重载版的
// 使用函数重载进行改造,
// 规则1: 由一个实现签名和多个重载签名组成
// 规则2: 由外部调用函数重载定义的函数时,只能调用重载签名,不能调用实现签名,实现签名下的函数体是给重载签名编写的
// 规则3: 调用重载函数时,会根据传入的参数来判断你调用的哪个函数
// 规则4: 只有一个函数体,只有实现签名配备了函数体
function ts_pickCard(x: object): number; // 重载签名
function ts_pickCard(x: string): object; // 重载签名
function ts_pickCard(x: any): any { // 实现签名
if (typeof x == 'object') {
return 1
}else if (typeof x == "string") {
return {
result : 1
}
}
}
ts_pickCard({})
ts_pickCard('1')
使用重载的最大好处是可以根据传入的参数,精准的识别应该返回什么类型,如下
在使用中值得注意的是当重载签名的传参类型不一致或者传参个数不一致的情况:
定义:实现签名参数个数可以少于重载签名的参数个数,但实现签名如果准备包含重载签名的某个位置的参数 ,那实现签名就必须兼容所有重载签名该位置的参数类型【联合类型或 any 或 unknown 类型的一种】。
- 传参类型不一致,但传参个数一致
// 重载签名1:a为stirng类型,
// 重载签名2:b为number类型,
// 实现签名:params的类型必须包含这两种类型,可以用any, unkonw, 联合类型(string | number)
function ts_pickCard(x: object, a: string): number; // 重载签名1
function ts_pickCard(x: number, b: number): object; // 重载签名2
function ts_pickCard(x: any, params: any): any { // 实现签名
if (typeof x == 'object') {
console.log('第一个重载',params)
return 1
}else if (typeof x == "number") {
console.log('第二个重载',params)
return {
result : 1
}
}
}
- 传参类型不一致,传参个数也不一致
// 重载签名1:只有一个参数,
// 重载签名2:有两个参数,且第二个参数b为number类型。
/*
实现签名:因为重载签名1只有一个参数,所以必须保证实现签名的params有默认值或者变为可选参数,且
params的类型必须包含number类型和默认值的类型,可以用any ,unknow, 联合类型(number | 默认值的
类型),优先用默认值
*/
function ts_pickCard(x: object): number; // 重载签名1
function ts_pickCard(x: number, b: number): object; // 重载签名2
function ts_pickCard(x: any, params: any = '1'): any { // 实现签名
// function ts_pickCard(x: any, params?: any): any { // 实现签名
if (typeof x == 'object') {
console.log('第一个重载',params)
return 1
}else if (typeof x == "number") {
console.log('第二个重载',params)
return {
result : 1
}
}
}
二,方法重载和构造函数重载
方法和class的构造器均可以使用重载.方法重载和函数重载差不多。
// 构造器隐式返回this,所以不需要有返回值。
class person {
private name: string
private age: number
constructor(name: string, age: number)
constructor(personInfo: Record<string, any>)
constructor(param: any, age: number = 18){
this.name = typeof param == 'object' ? param.name : param
this.age = age
}
}