繁体   English   中英

如何实现打字稿函数重载

[英]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;
}

为了满足具有多个(即重载)调用签名的接口,函数的实现必须能够处理所有此类签名。 如果fnFn<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

Playground 链接到代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM