关键词:TS 泛型
TypeScript 的泛型是一种工具,它能够使代码更加灵活,能够适配多种类型而非单一的类型。泛型可以创建可重用的组件,这些组件可以支持多种类型的数据,而不失去类型检查时的安全性。
泛型的基本概念
在 TypeScript 中, 泛型使用一个类型变量,常见的类型变量有 T
,U
,V
等。通过类型变量,你可以创建一个可以适应任何类型的组件(比如函数、接口或类)。类型变量像是函数或类的一个特殊参数,但这个参数是类型而非具体的值。
泛型的使用场景
- 函数:你可以创建一个泛型函数,该函数可以接受任意类型的参数,同时保证输入参数和返回参数类型相同:
function identity<T>(arg: T): T {
return arg;
}
这里 T
用作类型变量,可以捕获用户提供的类型(比如 number
),然后这个类型将被用于函数的参数和返回类型。
- 接口:使用泛型定义接口可以创建可用于多种类型的接口。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
这里 GenericIdentityFn
接口定义了一个属性,它是一个接收 T
类型参数并返回 T
类型的函数。
- type:
type
关键字可以用来创建类型别名,它确实支持泛型。你可以为类型别名定义泛型参数,然后在使用该类型别名时指定具体的类型。
下面是使用泛型的类型别名的例子:
// 这里定义了一个带有泛型参数 T 的类型别名
type Container<T> = {
value: T;
};
// 可以这样使用类型别名
let numberContainer: Container<number> = { value: 1 };
let stringContainer: Container<string> = { value: "Hello" };
// 使用类型别名定义函数类型
type ReturnFunction<T> = () => T;
// 这个函数返回一个数字
let myFunction: ReturnFunction<number> = () => 42;
// 使用带有两个参数的泛型
type KeyValue<K, V> = {
key: K;
value: V;
};
let keyValue: KeyValue<string, number> = { key: "testKey", value: 123 };
通过使用泛型,type
可以定义灵活的类型别名,使得别名能够用于各种不同的数据类型,同时保持类型的安全性。这使得你可以在类型别名中使用泛型来捕获传递给别名的类型信息。
- 类:泛型也可以用于类定义中,使得类可以灵活地与多种类型协作。
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>
类具有一个类型为 T
的属性 zeroValue
和一个用两个 T
类型参数返回 T
类型的方法 add
。
泛型约束
有时你可能希望对泛型进行限制,只允许使用满足特定接口的类型。这称为泛型约束。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
在这里,我们约束了类型 T
必须遵从 Lengthwise
接口,确保传入的类型具有 length
属性。
泛型中使用类型参数
你还可以在泛型中使用类型参数本身。
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3 };
getProperty(x, "a"); // Okay
getProperty(x, "m"); // Error: Argument of type '"m"' isn't assignable to '"a" | "b" | "c"'
在这个示例中,getProperty
函数有两个参数:obj
和 key
,obj
是对象 T
,key
是 T
中键的集合 keyof T
的成员。
通过泛型,TypeScript 允许你在保持类型安全的同时创建灵活,可适用于多种类型的组件。这样你就能够写出更加通用且易于复用的代码。