TypeScript 泛型
泛型是TypeScript最强大的特性之一,它可以让我们在编写代码时保持类型的灵活性,同时又不失类型安全。
1. 泛型基础
1.1 泛型函数
// 基本泛型函数
function identity<T>(value: T): T {
return value;
}
// 使用方式
let result1 = identity<string>("hello"); // 显式指定类型
let result2 = identity(42); // 类型推断
// 多个类型参数
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
let pair1 = pair<string, number>("hello", 42);
let pair2 = pair(true, [1, 2, 3]);
1.2 泛型接口
// 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
// 实现泛型接口
let myIdentity: GenericIdentityFn<number> = function(arg: number): number {
return arg;
};
// 泛型接口作为类型
interface Collection<T> {
add(item: T): void;
remove(item: T): void;
getItems(): T[];
}
class List<T> implements Collection<T> {
private items: T[] = [];
add(item: T): void {
this.items.push(item);
}
remove(item: T): void {
const index = this.items.indexOf(item);
if (index > -1) {
this.items.splice(index, 1);
}
}
getItems(): T[] {
return [...this.items];
}
}
1.3 泛型类
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zero: T, addFn: (x: T, y: T) => T) {
this.zeroValue = zero;
this.add = addFn;
}
}
// 数字类型实例
let numericAdder = new GenericNumber<number>(0, (x, y) => x + y);
console.log(numericAdder.add(10, 20)); // 30
// 字符串类型实例
let stringAdder = new GenericNumber<string>("", (x, y) => x + y);
console.log(stringAdder.add("Hello ", "World")); // "Hello World"
2. 泛型约束
2.1 使用extends关键字
// 基本约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在我们知道arg具有length属性
return arg;
}
// 可以传入string或array
loggingIdentity("hello"); // OK
loggingIdentity([1, 2, 3]); // OK
loggingIdentity(3); // Error: number没有length属性
// 多重约束
interface HasName {
name: string;
}
interface HasAge {
age: number;
}
function processUser<T extends HasName & HasAge>(user: T): void {
console.log(`${user.name} is ${user.age} years old`);
}
2.2 keyof约束
// 使用keyof获取对象的键类型
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let person = {
name: "John",
age: 30,
location: "New York"
};
// 类型安全的属性访问
let name = getProperty(person, "name"); // OK
let age = getProperty(person, "age"); // OK
let email = getProperty(person, "email"); // Error: "email"不是person的属性
3. 高级泛型模式
3.1 条件类型
// 基本条件类型
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
// 分布式条件类型
type NonNullable<T> = T extends null | undefined ? never : T;
type C = NonNullable<string | number | null>; // string | number
// 推断类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function fn(x: number): string {
return x.toString();
}
type FnReturn = ReturnType<typeof fn>; // string