TypeScript范型
在TypeScript中,范型(Generics)是一种强大的工具,它允许你在定义函数、接口或类时不具体指定类型,而是在使用时再指定。这样做的好处是增加了代码的复用性和类型安全性。范型通过参数化类型来工作,使得你可以编写与类型无关的代码,同时保持类型检查。
1. 范型函数
范型函数允许你在函数定义时不指定具体的类型,而是在调用函数时指定。
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString"); // 类型参数为string
let output2 = identity<number>(42); // 类型参数为number
在这个例子中,identity
函数是一个范型函数,它接受一个类型为 T
的参数 arg
并返回相同类型的值。在调用 identity
函数时,我们通过 <string>
和 <number>
来指定类型参数。
你也可以让TypeScript编译器自动推断类型参数,而不需要显式指定:
let output3 = identity("anotherString"); // 自动推断为string
let output4 = identity(34); // 自动推断为number
2. 范型接口
范型接口允许你在接口中定义一个或多个类型参数,这些类型参数可以在接口的方法或属性中使用。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identityFn<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identityFn;
console.log(myIdentity(42)); // 输出: 42
在这个例子中,GenericIdentityFn
是一个范型接口,它描述了一个接受一个类型为 T
的参数并返回相同类型值的函数。然后,我们定义了一个符合 GenericIdentityFn<number>
类型的函数 identityFn
,并将其赋值给 myIdentity
变量。
3. 范型类
范型类允许你在类定义中引入类型参数,这些类型参数可以在类的属性、方法或构造函数中使用。
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, add: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = add;
}
}
let myGenericNumber = new GenericNumber<number>(0, function(x, y) { return x + y; });
console.log(myGenericNumber.add(1, 2)); // 输出: 3
在这个例子中,GenericNumber
是一个范型类,它有两个属性:zeroValue
和 add
。zeroValue
是类型为 T
的值,add
是一个接受两个类型为 T
的参数并返回类型为 T
的值的函数。然后,我们创建了一个 GenericNumber<number>
类型的实例,并为其提供了适当的 zeroValue
和 add
函数。
4. 泛型约束
有时,你可能希望对你使用的泛型进行约束,以确保它们至少具有某些属性或方法。这可以通过泛型约束来实现。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在我们知道arg具有length属性,因为T被约束为Lengthwise
return arg;
}
loggingIdentity({ length: 10, value: "hello!" }); // 输出: 10
loggingIdentity([1, 2, 3]); // 输出: 3
在这个例子中,我们定义了一个 Lengthwise
接口,它有一个 length
属性。然后,我们定义了一个 loggingIdentity
函数,它接受一个类型为 T
的参数,其中 T
被约束为 Lengthwise
。这意味着 T
必须具有 length
属性。
5. 使用 keyof
和 typeof
在泛型约束中
keyof
和 typeof
是TypeScript中的高级类型操作,它们可以与泛型约束一起使用来创建更复杂的类型关系。
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let person = { name: "Alice", age: 30 };
console.log(getProperty(person, "name")); // 输出: Alice
console.log(getProperty(person, "age")); // 输出: 30
在这个例子中,getProperty
函数接受一个对象 obj
和一个字符串 key
,其中 key
是 obj
的一个键。函数返回 obj[key]
的值,其类型为 T[K]
。这里,K
被约束为 keyof T
,意味着 K
必须是 T
的一个键。
范型是TypeScript中一个非常重要的特性,它允许你编写更加灵活和可重用的代码,同时保持类型安全性。通过定义范型函数、接口和类,以及使用泛型约束和高级类型操作,你可以创建出强大且易于维护的TypeScript应用程序。
本文地址:https://www.tides.cn/p_typescript-generics