[英]how to implement typescript function overload
如何实现打字稿函数重载?
interface Fn <T>{
(payload: string): T;
(payload: string, a: T): T;
}
let fn: Fn<number> = function(a: string, b: number) {
return b
}
报告Type '(a: string, b: number) => string' is not assignable to type 'Fn<number>'.Vetur(2322)
为了使这两个重载都适用于fn
,您必须在实现中将b
设为可选。 当你这样做时,你会看到一个不同的错误,因为我们的类型说我们必须返回一个number
,所以当b
可能undefined
时返回b
并不能减少它。 我们可以为b
设置一个默认值,或者在函数体内返回一些默认值。
let fn: Fn<number> = function(a: string, b: number = 0) {
return b;
}
let fn: Fn<number> = function(a: string, b?: number) {
return b === undefined ? 0 : b;
}
为了满足具有多个(即重载)调用签名的接口,函数的实现必须能够处理所有此类签名。 如果fn
是Fn<number>
,那么您必须能够像这样调用它:
fn("someString"); // first overload
fn("someString", 1234); // second overload
但实施
function (a: string, b: number) {
return b
}
不满足第一个重载(因为b
将是undefined
),因此不可分配给Fn<number>
。
相反,您应该考虑提出与两个调用签名兼容的实现。 例如:
let fn: Fn<number> = function (a: string, b?: number) {
return b ?? a.length
}
在这里,实现要求它的第一个参数a
是一个string
并采用一个可选的第二个参数b
类型为number
。 由于b
可能undefined
并且您必须返回一个number
,因此您不能直接返回b
。 在上面我返回b
除非它是undefined
,在这种情况下我返回a.length
。 这始终是一个number
,编译器可以验证分配是否有效。
注意:在重载调用签名具有不同返回类型的情况下会出现复杂情况。 除非您的函数表达式的实现返回所有返回类型的交集,否则编译器将无法验证类型安全并会出错,因此您需要使用类型断言:
interface OtherFn {
(payload: string): string;
(payload: string, a: number): number;
}
let fn2: OtherFn = (a: string, b?: number) => b ?? a; // error!
// ~~~ <-- string | number not assignable to string
console.log(fn2("abc").toUpperCase()) // ABC
console.log(fn2("abc", Math.PI).toFixed(2)) // 3.14
在这里您可以看到fn2
确实满足OtherFn
两个调用签名,但是由于返回类型不同,编译器无法对其进行验证。 如果要使用函数表达式执行此操作,则需要类型断言:
let fn3 = ((a: string, b?: number) => b ?? a) as OtherFn; // okay
或者你可以放弃函数表达式和使用功能的语句,检查较为松散,允许返回类型是联合所有的呼叫签名返回类型:
function fn4(payload: string): string;
function fn4(payload: string, a: number): number;
function fn4(a: string, b?: number) {
return b ?? a;
}
尽管没有像这样手动注释,但可以看出满足OtherFn
。
let fn5: OtherFn = fn4; // okay
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.