如何在 Typescript 中定义泛型函数类型;两种类似的方式?

Jus*_*inM 9 typescript typescript-generics

我正在尝试在 Typescript 中定义一些通用函数类型。似乎有两种类似的方法可以做到这一点,而且它们都有效。然而,第二种形式 - 见下文ConcatY- 似乎并不那么灵活,或者至少我不知道如何指示函数采用具有特定参数类型的其中之一。有没有办法定义一个接受ConcatY数字的函数?一般来说,我应该如何考虑这两种定义泛型函数的方法之间的差异?

// Two similar looking function types
type ConcatX<T> = (a: T, b: T) => T;
type ConcatY = <T>(a: T, b: T) => T;

// Can create instances of each of these types
const sum: ConcatX<number> = (a, b) => a + b;
const product: ConcatY = (a: number, b: number) => a + b;

// Can define a function that takes a ConcatX
function DoMathX(sum: ConcatX<number>) {
  console.log(`1 + 1 is ${sum(1, 1)}`);
}

// But can't define a function that takes a ConcatY for numbers
// A and B are "unknown"
// Or is there a way?
function DoMathTwo(sum: ConcatY) {}

Run Code Online (Sandbox Code Playgroud)

Ale*_*yne 10

这:

type ConcatX<T> = (a: T, b: T) => T;
Run Code Online (Sandbox Code Playgroud)

是泛型类型别名,其中包含使用泛型参数的函数。一旦类型被解析,该函数使用的通用参数就会被锁定。当某种类型需要设置函数的类型时,这会很方便。

例如这里:

const sum: ConcatX<number> = (a, b) => a + b;
Run Code Online (Sandbox Code Playgroud)

这表示,在该函数的外部,您声明该函数的参数是数字。

请注意,这根本不是函数类型的真正一部分。这种方法与以下方法没有本质上的不同:

type ContatX<T> = { sum(a: T, b: T): T, someValue: T }
Run Code Online (Sandbox Code Playgroud)

要点是T完全在函数外部设置,函数只是选择它来使用。


这:

type ConcatY = <T>(a: T, b: T) => T;
Run Code Online (Sandbox Code Playgroud)

是一个通用函数通用参数在调用函数时设置,并且每次调用时都可以不同。并且该参数可以从参数和的类型推断出来。ab

要在此处输入防止错误使用的代码,您需要检查返回类型:

const resultStr: string = sum(1,2) // error: cannot assign number to string
const resultNum: number = sum('a','b') // error: cannot assign string to number
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,函数调用都是完全有效的,但结果不是类型系统所期望的,因此您会收到错误。


如果您想要 concat 的特定子类型,其中参数必须是数字,那么您需要泛型类型ConcatX

但是,如果您的函数可以接受许多不同的参数,并且返回类型取决于这些参数的类型,并且您事先不知道将使用什么类型调用它将,那么您需要泛型函数ContactY

这一切都意味着如果你想:

“指示函数采用具有特定参数类型的其中之一”

然后,您需要使用ContactX通用参数来创建一个锁定T为您想要的任何内容的函数类型。