在本章中,我们将探讨如何使用泛型来增强Deno中的类型系统。泛型允许我们编写更加灵活和可重用的代码,同时保持类型安全。
什么是泛型?
泛型是一种编程技术,它允许你编写可以适用于多种数据类型的代码。通过使用泛型,我们可以创建能够处理任意类型数据的函数、类或接口,而无需牺牲类型安全性。
泛型函数
定义泛型函数
泛型函数允许我们在定义函数时指定一个或多个类型参数,这些类型参数可以在函数体中使用。这样,我们可以根据需要传入不同的类型,同时保持编译时的类型检查。
function identity<T>(arg: T): T { return arg; }
在这个例子中,identity
函数接受一个类型为 T
的参数,并返回一个类型为 T
的值。这里的 T
就是一个类型参数,代表任何类型。
使用泛型函数
我们可以使用任何类型调用这个泛型函数:
let output = identity<string>("myString"); // 类型为 string let output2 = identity<number>(99); // 类型为 number
或者,如果我们不指定类型,TypeScript 会自动推断类型:
let output3 = identity("hello world"); // 类型为 string
多个类型参数
我们也可以为函数定义多个类型参数:
function swap<T, U>(tuple: [T, U]): [U, T] { return [tuple[1], tuple[0]]; } let result = swap([7, "seven"]); // 结果是 ["seven", 7]
泛型类
泛型类的定义
泛型类允许我们在类定义中指定类型参数。这使得类的实例化可以使用不同的类型。
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; };
在这个例子中,GenericNumber
类使用了一个类型参数 T
。当我们创建该类的一个实例时,必须提供一个具体类型。
泛型接口
泛型接口的定义
接口也可以是泛型的,这意味着接口可以描述具有特定类型的属性或方法。
interface Pair<T, U> { first: T; second: U; } let myPair: Pair<string, number> = {first: "hello", second: 7};
在这个例子中,Pair
接口有两个类型参数 T
和 U
,分别表示 first
和 second
属性的类型。
泛型约束
约束泛型类型
有时候我们需要限制类型参数可以使用的类型。例如,如果我们要操作数组,可能希望类型参数支持某些方法(如 length
属性)。为此,我们可以使用泛型约束。
-- -------------------- ---- ------- --------- ---------- - ------- ------- - -------- ----------------- ------- ---------------- --- - - ------------------------ -- ------- ------- --- ------ ---- - ------------------------ --- ------ ---- -- --
在这个例子中,我们定义了一个接口 Lengthwise
,它有一个 length
属性。然后我们定义了一个 loggingIdentity
函数,它接受一个类型参数 T
,但要求 T
必须满足 Lengthwise
接口。这样,我们就可以在函数体内使用 arg.length
属性了。
泛型实用技巧
默认类型
使用默认类型
有时我们可能想要给泛型参数提供一个默认类型。当用户没有提供类型参数时,就使用默认类型。
-- -------------------- ---- ------- -------- ------------- - --------------- ------- ------ --- --- - --- ------- --- - --- --- ---- - - -- - - ------- ---- - --------- - ------ - ------ ------- - -------------------------- ------ -- ----- ---- ----
在这个例子中,如果用户没有指定类型参数,那么 createArray
函数将使用 string
作为默认类型。
泛型工具类型
利用工具类型
TypeScript 提供了一些内置的工具类型,它们可以帮助我们更方便地操作泛型类型。例如,Partial
工具类型可以将对象的所有属性变为可选的。
-- -------------------- ---- ------- ---- ---------- - - -- -- ----- ---- ----- -- --------- ---- - ----- ------- ---- ------- - ---- ----------- - -------------- --- ----- ----------- - - ----- ------- -- -- ---------
在这个例子中,我们定义了一个 PartialUser
类型,它是 User
类型的一个变体,其中所有属性都是可选的。
总结
泛型是 TypeScript 中非常强大的功能,它使我们的代码更加灵活和可重用。通过合理使用泛型,我们可以创建出既强大又类型安全的程序。在接下来的部分中,我们将继续探索更多关于泛型的高级用法。