我正在尝试在 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) {}
type ConcatX<T> = (a: T, b: T) => T;
是泛型类型别名,其中包含使用泛型参数的函数。一旦类型被解析,这个函数使用的泛型参数就会被锁定。当某些类型需要设置函数的类型时,这会很方便。
例如这里:
const sum: ConcatX<number> = (a, b) => a + b;
这表示,在此函数的外部,您声明此函数的参数是数字。
请注意,这根本不是函数类型的一部分。这种方法与以下方法没有根本区别:
type ContatX<T> = { sum(a: T, b: T): T, someValue: T }
关键是T
完全设置在函数之外,函数只是选择使用它。
type ConcatY = <T>(a: T, b: T) => T;
是一个泛型函数。泛型参数在调用函数时设置,每次调用时都可以不同。并且可以从参数和的类型推断该参数。a
b
你不能T
在这里提前锁定,因为T
是在调用函数时决定的,而不是更早。
这意味着没有ConcatY
只需要数字的子类型。要在此处输入防止不良使用,您可以检查返回类型:
const resultStr: string = sum(1,2) // error: cannot assign number to string
const resultNum: num = sum('a','b') // error: cannot assign string to number
在这两种情况下,函数调用都是完全有效的,但结果不是类型系统所期望的,因此您会收到错误消息。
如果您想要参数必须是数字的特定 concat 子类型,那么您需要泛型类型ConcatX
。
但是,如果您的函数可以接受许多不同的参数,并且返回类型取决于这些参数的类型,并且您不知道提前调用它的确切类型,那么您需要泛型 function ContactY
。
这一切都意味着,如果您想:
“指示一个函数采用具有特定参数类型的其中之一”
然后你需要使用ContactX
一个泛型参数来创建一个T
锁定到任何你想要的函数类型。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句