Typescript 泛型是一种获取具有参数的函数的方法,我们可以在调用该参数时定义该参数 – 就像我们可以在调用函数时更改函数的参数一样。
如果您不熟悉 Typescript 泛型的概念,请继续阅读以了解它们的工作原理。
Typescript 泛型如何工作#
想象一个像下面这样的函数 – 它有一个字符串类型的参数,并在其上输出一个字符串:
let myFunction = function(arg: string):string {
return `Hello, the value of your argument is ${arg}`;
}
// This will return "Hello, the value of your argument is World"
myFunction("World");
有趣的是,myFunction
两者都适用于多种类型,例如 astring
或number
. 当我们在多种不同的情况下使某些东西工作时,它被称为泛型,而这正是Typescript 泛型的含义。
为了将我们的 Typescript 函数调整为泛型,我们在<>
s 中直接在 function 关键字之后添加一个可定义的参数:
let myFunction = function<NewType>(arg: NewType):string {
return `Hello, the value of your argument is ${arg}`;
}
// This will return "Hello, the value of your argument is World"
myFunction<number>(5);
将 Typescript 中的泛型参数视为与 vanilla Javascript 中的参数相同的方式。在上面的示例中,我们创建了一个新参数,称为NewType
– 但您可以将其命名为任何名称。我们的论点arg
是 类型NewType
。
然后,当我们调用 时myFunction()
,我们可以定义参数的类型——在上面的例子中,是一个数字。
具有多种类型的泛型#
想象另一个例子,我们没有使用字符串字面量——在下面的例子中,我们简单地将两个参数相加:
let myFunction = function(x: string, y: string):string {
return x + y;
}
// Returns HelloWorld
myFunction("Hello", "World");
同样,这适用于多种类型 – 最显着的是字符串和数字。让我们再次尝试添加一个泛型类型:
let myFunction = function<NewType>(x: NewType, y: NewType):number {
return x.length + y.length;
}
除了这一次,我们会得到一个错误:
Property 'length' does not exist on type 'NewType'
这引发错误的原因是因为我们没有定义什么NewType
可以做什么不能做什么。NewType
为了解决这个例子,我们只需要使用[]
括号提到 x 和 y 将是一个 s 数组:
let myFunction = function<NewType>(x: NewType[], y: NewType[]):number {
return x.length + y.length;
}
// This will return 6 (3 + 3)
myFunction<number>([ 5, 6, 7 ], [ 10, 9, 8 ]);
扩展泛型类型
然而,有时我们会遇到不同的情况。我们可能会遇到想要扩展的情况NewType
,例如,如果我们正在访问一个NewType
应该具有但编译器不知道的属性。extends
我们可以使用关键字扩展泛型类型。这意味着我们可以约束传递给函数的任何类型,因此它们具有最少的属性集。
在下面的示例中,所有类型的元素NewType
都应至少具有以下属性name
:
type ExtendedNewType = {
name: string
}
type User = {
name: string,
age?: number
}
// NewType must contain at least the attribute "name" - so lets add it as an extension of our ExtendedNewType type.
let myFunction = function<NewType extends ExtendedNewType>(x: NewType, y: NewType):string {
return `${x.name} ${y.name}`
}
// This will return "Hello World"
let runFunction = myFunction<User>({ name: "Hello" }, { name: "World" });
自定义类型
我们在上面定义自定义类型。如果您不熟悉自定义类型,请尝试阅读我们在 Typescript 中创建自定义类型的指南
通用自定义类型#
除了将泛型类型应用于我们的函数之外,我们还可以将它们应用于我们自己的自定义类型。在下面的示例中,我们有一个 ID 可能是字符串或数字的用户。我们可以在新类型的顶层定义一个泛型类型,然后在我们使用该User
类型时定义它。
// Type User can have an ID which is either a number or a string
type User<CustomType extends (number | string)> = {
id: CustomType,
name?: string,
age?: number
}
// In this case, we define CustomType as a string
let myUser:User<string> = {
id: "1234-1234-1234",
name: "John Doe",
age: 24
}
// In this case, we define CustomType as a number
let myOtherUser:User<number> = {
id: 1234,
name: "Jane Seymore",
age: 48
}