简体   繁体   English

打字稿中的函数类型重载

[英]Overloaded function type in typescript

How can I create a function type, without providing a concrete function, that is overloaded? 如何在不提供具体功能的情况下创建重载的函数类型? By inspecting the type of an overloaded function, it seems multiple call signatures on an interface/object type are the way to go: 通过检查重载函数的类型,似乎可以使用接口/对象类型上的多个调用签名:

function a(input: string): string
function a(input: number): number
function a(input: string | number): string | number {
  return input
}

type A = typeof a

type B = {
  (input: string): string
  (input: number): number
}

const b: B = a // Okay!

Defining the same idea with a union type (without that pesky catch-all case that you need to make overloads happy) also works , the types are compatible in both directions! 定义同样的想法与联合类型(不,你需要做的重载高兴讨厌的包罗万象的情况下) 也适用 ,该类型是双向兼容!

type C = ((input: number) => number) & ((input: string) => string)

const c: C = b // Okay!

const a2: A = c // Okay too!

But how do I now make a function fitting this type? 但是,现在如何制作适合这种类型的功能? Do I have to necessarily also use overloading? 我是否也必须使用重载?

const x: A = (input: string | number) => input

and

const y: A = (input: string | number) => {
  if (typeof input === "number") return input
  if (typeof input === "string") return input
  throw "excrement"
}

both fail with the exact same following error: 两者均因以下完全相同的错误而失败:

Type '(input: string | number) => string | number' is not assignable to type '{ (input: string): string; (input: number): number; }'.
  Type 'string | number' is not assignable to type 'string'.
    Type 'number' is not assignable to type 'string'.

Worst of all, this happens even if I use the less readable union type C 最糟糕的是,即使我使用可读性较低的联合类型C ,也会发生这种情况

Type '(input: string | number) => string | number' is not assignable to type 'C'.
  Type '(input: string | number) => string | number' is not assignable to type '(input: number) => number'.
    Type 'string | number' is not assignable to type 'number'.
      Type 'string' is not assignable to type 'number'.

Hopefully, I am doing something obvious wrong and there's an easy fix. 希望我正在做一些明显的错误,并且有一个简单的解决方法。 Else, what are my best options when I need to demand that a function that is passed somewhere handle several call signatures with corresponding return types? 否则,当我需要传递到某个地方的函数处理具有相应返回类型的多个调用签名时,最好的选择是什么?

To define a function with multiple call signatures, if you're not able to write a single call signature that is assignable to all the call signatures you want, you will have to use either overloading (which has looser rules for compatibility of the call signatures with the implementation signature) or a type assertion. 要定义具有多个呼叫签名的功能,如果您无法编写可分配给所需的所有呼叫签名的单个呼叫签名,则必须使用两种重载方法(为了保证呼叫签名的兼容性,该规则具有较宽松的规则)带有实现签名)或类型断言。 You aren't missing anything. 您什么都不会错过。

You can solve this using a generic declaration: 您可以使用通用声明来解决此问题:

type Input = string | number

function a<T extends Input>(input: T): T {
  return input
}

type A = typeof a

type B = {
  (input: string): string
  (input: number): number
}

const b: B = a // Okay!

type C = ((input: number) => number) & ((input: string) => string)

const c: C = b // Okay!

const a2: A = c // Okay too!

As for x and y , you cannot define the parameter type loosely and expect the output type to be inferred strictly. 对于xy ,您不能宽松地定义参数类型,并且不能期望严格推断输出类型。 Omit defining the input types for the functions if you're going to declare x and y as type A : 如果要将xy声明为A类型,则忽略为函数定义输入类型:

const x: A = input => input

const y: A = input => {
  if (typeof input === "number") return input
  if (typeof input === "string") return input
  throw "excr"
}

You can verify everything above works at this TypeScript Playground demo . 您可以在此TypeScript Playground演示中验证以上所有内容是否正常。

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

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