迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 >

Typescript 泛型的工作原理

作者:迹忆客 最近更新:2022/05/07 浏览次数:

Typescript 泛型是一种获取具有参数的函数的方法,我们可以在调用该参数时定义该参数 - 就像我们可以在调用函数时更改函数的参数一样。

如果不熟悉 Typescript 泛型的概念,请继续阅读来了解它们的工作原理。

Typescript 泛型如何工作

想象一个像下面这样的函数 - 它有一个字符串类型的参数,并在其上输出一个字符串:

let myFunction = function(arg: string):string {
    return `Hello, 您的参数的值是 ${arg}`;
}
// 这将返回“您好,您的参数的值是 World”
myFunction("World");

有趣的是,myFunction 可以处理多种类型,例如字符串或数字。 当我们在多种不同的情况下使某些东西工作时,它被称为泛型,而这正是 Typescript 泛型的含义。

为了将我们的 Typescript 函数调整为通用函数,我们在 <> 中直接在 function 关键字之后添加一个可定义的参数:

let myFunction = function<NewType>(arg: NewType):string {
    return `Hello, 参数的值是 ${arg}`;
}
// 将返回 "Hello, 参数的值是 5"
myFunction<number>(5);

将 Typescript 中的泛型参数视为与 vanilla Javascript 中的参数相同的方式。 在上面的示例中,我们创建了一个名为 NewType 的新参数 - 但我们可以将其命名为任何名称。 我们的参数 arg 是 NewType 类型。

然后,当我们调用 myFunction() 时,我们可以定义参数的类型——在上面的例子中,是一个数字。


具有多种类型的泛型

想象另一个例子,我们没有使用字符串字面量——在下面的例子中,我们简单地将两个参数相加:

let myFunction = function(x: string, y: string):string {
    return x + y;
}

// 返回 HelloWorld
myFunction("Hello", "World");

同样,这适用于多种类型 - 最显著的是字符串和数字。 让我们再次尝试添加一个泛型类型:

Copylet myFunction = function<NewType>(x: NewType, y: NewType):number {
    return x.length + y.length;
}

这会产生一个错误:

typescript 泛型错误

这引发错误的原因是因为我们还没有定义 NewType 可以做什么和不能做什么。 为了解决这个例子中的问题,我们只需要使用 [] 将 x 和 y 作为一个 NewTypes 数组:

let myFunction = function<NewType>(x: NewType[], y: NewType[]):number {
    return x.length + y.length;
}
// 这将返回 6 (3 + 3)
myFunction<number>([ 5, 6, 7 ], [ 10, 9, 8 ]);

扩展泛型类型

然而,有时我们会遇到不同的情况。 我们可能会遇到想要扩展 NewType 的情况,例如,如果我们正在访问 NewType 应该具有但编译器不知道的属性。 我们可以使用 extends 关键字扩展泛型类型。 这意味着我们可以约束传递给函数的任何类型,因此它们具有最少的属性集。

在下面的示例中,NewType 类型的所有元素都应至少具有属性名称:

type ExtendedNewType = {
    name: string
}

type User = {
    name: string,
    age?: number
}

// NewType 必须至少包含属性“name”——所以让我们将其添加为 ExtendedNewType 类型的扩展。
let myFunction = function<NewType extends ExtendedNewType>(x: NewType, y: NewType):string {
    return `${x.name} ${y.name}`
}
// 这将返回 "Hello World"
let runFunction = myFunction<User>({ name: "Hello" }, { name: "World" });

泛型自定义类型

除了将泛型类型应用于我们的函数之外,我们还可以将它们应用于我们自己的自定义类型。 在下面的示例中,我们有一个 ID 可能是字符串或数字的用户。 我们可以在新类型的顶层定义一个泛型类型,然后在我们使用 User 类型时定义它。

// 类型用户可以有一个 ID,它可以是数字或字符串
type User<CustomType extends (number | string)> = {
    id: CustomType,
    name?: string,
    age?: number
}

// 在这种情况下,我们将 CustomType 定义为字符串
let myUser:User<string> = {
    id: "1234-1234-1234",
    name: "John Doe",
    age: 24
}

// 在这种情况下,我们将 CustomType 定义为一个数字
let myOtherUser:User<number> = {
    id: 1234,
    name: "Jane Seymore",
    age: 48
}

除非注明转载,本站文章均为原创或翻译,欢迎转载,转载请以链接形式注明出处

本文地址:

迹忆客

专注技术分享,项目实战分享!

技术宅 乐于分享 7年编程经验
社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

热门文章

教程更新

热门标签

扫码一下
查看教程更方便