TypeScript_学习资料_泛型深度解析

21 阅读10分钟

TypeScript 泛型深度解析

目录

  1. 泛型概述
  2. 泛型函数
  3. 泛型接口
  4. 泛型类
  5. 泛型约束
  6. 高级泛型模式
  7. 条件类型
  8. 映射类型
  9. 实用工具类型
  10. 实战案例

泛型概述

什么是泛型?

泛型(Generics)是 TypeScript 中最强大的特性之一,它允许我们创建可重用的组件,这些组件可以支持多种类型,而不是单一类型。泛型提供了一种方式来创建可重用的代码,同时保持类型安全。

为什么需要泛型?

// 没有泛型的问题
function identityString(arg: string): string {
    return arg;
}

function identityNumber(arg: number): number {
    return arg;
}

function identityBoolean(arg: boolean): boolean {
    return arg;
}

// 使用 any 的问题
function identityAny(arg: any): any {
    return arg; // 失去了类型信息
}

// 泛型解决方案
function identity<T>(arg: T): T {
    return arg; // 保持类型信息,同时支持多种类型
}

泛型的基本语法

// 基本泛型函数
function genericFunction<T>(arg: T): T {
    return arg;
}

// 多个类型参数
function pair<T, U>(first: T, second: U): [T, U] {
    return [first, second];
}

// 使用泛型
let result1 = genericFunction<string>("hello");    // 显式指定类型
let result2 = genericFunction("hello");            // 类型推断
let result3 = pair<string, number>("hello", 42);   // 多个类型参数

泛型函数

1. 基础泛型函数

// 简单的泛型函数
function firstElement<T>(arr: T[]): T | undefined {
    return arr[0];
}

// 使用示例
let numbers = [1, 2, 3, 4, 5];
let firstNumber = firstElement(numbers); // number | undefined

let strings = ["hello", "world"];
let firstString = firstElement(strings); // string | undefined

// 显式指定类型
let firstAny = firstElement<any>([1, "hello", true]); // any | undefined

2. 多参数泛型函数

// 两个类型参数
function map<T, U>(array: T[], transform: (item: T) => U): U[] {
    return array.map(transform);
}

// 使用示例
let numbers = [1, 2, 3, 4, 5];
let strings = map(numbers, n => n.toString()); // string[]
let doubled = map(numbers, n => n * 2);        // number[]

// 三个类型参数
function reduce<T, U, V>(
    array: T[], 
    transform: (item: T) => U, 
    reducer: (acc: V, current: U) => V, 
    initial: V
): V {
    return array.map(transform).reduce(reducer, initial);
}

3. 泛型函数的重载

// 泛型函数重载
function process<T>(value: T): T;
function process<T>(value: T[]): T[];
function process<T>(value: T | T[]): T | T[] {
    if (Array.isArray(value)) {
        return value.map(item => item); // 处理数组
    } else {
        return value; // 处理单个值
    }
}

// 使用
let singleValue = process("hello");        // string
let arrayValue = process(["a", "b", "c"]); // string[]

4. 异步泛型函数

// 异步泛型函数
async function fetchData<T>(url: string): Promise<T> {
    const response = await fetch(url);
    return response.json() as T;
}

// 使用示例
interface User {
    id: number;
    name: string;
    email: string;
}

async function getUser(id: number): Promise<User> {
    return fetchData<User>(`/api/users/${id}`);
}

async function getUsers(): Promise<User[]> {
    return fetchData<User[]>('/api/users');
}

泛型接口

1. 基础泛型接口

// 简单的泛型接口
interface Container<T> {
    value: T;
    getValue(): T;
    setValue(value: T): void;
}

// 实现泛型接口
class StringContainer implements Container<string> {
    constructor(public value: string) {}
    
    getValue(): string {
        return this.value;
    }
    
    setValue(value: string): void {
        this.value = value;
    }
}

class NumberContainer implements Container<number> {
    constructor(public value: number) {}
    
    getValue(): number {
        return this.value;
    }
    
    setValue(value: number): void {
        this.value = value;
    }
}

2. 函数类型的泛型接口

// 泛型函数接口
interface Transformer<T, U> {
    (input: T): U;
}

// 使用泛型函数接口
let stringToNumber: Transformer<string, number> = (str) => parseInt(str);
let numberToString: Transformer<number, string> = (num) => num.toString();
let booleanToString: Transformer<boolean, string> = (bool) => bool ? "true" : "false";

// 更复杂的函数接口
interface Comparator<T> {
    (a: T, b: T): number;
}

interface Sorter<T> {
    sort(array: T[], comparator?: Comparator<T>): T[];
}

class ArraySorter<T> implements Sorter<T> {
    sort(array: T[], comparator?: Comparator<T>): T[] {
        if (comparator) {
            return [...array].sort(comparator);
        }
        return [...array].sort();
    }
}

3. 索引签名的泛型接口

// 泛型字典接口
interface Dictionary<T> {
    [key: string]: T;
}

// 使用示例
let stringDict: Dictionary<string> = {
    "name": "张三",
    "city": "北京"
};

let numberDict: Dictionary<number> = {
    "age": 30,
    "score": 95
};

// 更复杂的索引签名
interface Cache<T> {
    [key: string]: T;
    get(key: string): T | undefined;
    set(key: string, value: T): void;
    has(key: string): boolean;
    delete(key: string): boolean;
}

class MemoryCache<T> implements Cache<T> {
    [key: string]: any;
    private data: { [key: string]: T } = {};
    
    get(key: string): T | undefined {
        return this.data[key];
    }
    
    set(key: string, value: T): void {
        this.data[key] = value;
    }
    
    has(key: string): boolean {
        return key in this.data;
    }
    
    delete(key: string): boolean {
        if (this.has(key)) {
            delete this.data[key];
            return true;
        }
        return false;
    }
}

4. API 响应的泛型接口

// API 响应泛型接口
interface ApiResponse<T> {
    success: boolean;
    data: T;
    message: string;
    timestamp: Date;
    meta?: {
        total?: number;
        page?: number;
        limit?: number;
    };
}

// 分页响应接口
interface PaginatedResponse<T> extends ApiResponse<T[]> {
    meta: {
        total: number;
        page: number;
        limit: number;
        totalPages: number;
    };
}

// 使用示例
interface User {
    id: number;
    name: string;
    email: string;
}

// 单个用户响应
let userResponse: ApiResponse<User> = {
    success: true,
    data: { id: 1, name: "张三", email: "zhangsan@example.com" },
    message: "获取用户成功",
    timestamp: new Date()
};

// 用户列表响应
let usersResponse: PaginatedResponse<User> = {
    success: true,
    data: [
        { id: 1, name: "张三", email: "zhangsan@example.com" },
        { id: 2, name: "李四", email: "lisi@example.com" }
    ],
    message: "获取用户列表成功",
    timestamp: new Date(),
    meta: {
        total: 100,
        page: 1,
        limit: 10,
        totalPages: 10
    }
};

泛型类

1. 基础泛型类

// 简单的泛型类
class Stack<T> {
    private items: T[] = [];
    
    push(item: T): void {
        this.items.push(item);
    }
    
    pop(): T | undefined {
        return this.items.pop();
    }
    
    peek(): T | undefined {
        return this.items[this.items.length - 1];
    }
    
    isEmpty(): boolean {
        return this.items.length === 0;
    }
    
    size(): number {
        return this.items.length;
    }
    
    toArray(): T[] {
        return [...this.items];
    }
}

// 使用泛型类
let numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);

let stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");

2. 泛型类的继承

// 基础泛型类
class Collection<T> {
    protected items: T[] = [];
    
    add(item: T): void {
        this.items.push(item);
    }
    
    get(index: number): T | undefined {
        return this.items[index];
    }
    
    size(): number {
        return this.items.length;
    }
}

// 继承泛型类
class SortedCollection<T> extends Collection<T> {
    private compareFn?: (a: T, b: T) => number;
    
    constructor(compareFn?: (a: T, b: T) => number) {
        super();
        this.compareFn = compareFn;
    }
    
    add(item: T): void {
        super.add(item);
        this.sort();
    }
    
    private sort(): void {
        if (this.compareFn) {
            this.items.sort(this.compareFn);
        } else {
            this.items.sort();
        }
    }
}

// 使用
let sortedNumbers = new SortedCollection<number>((a, b) => a - b);
sortedNumbers.add(3);
sortedNumbers.add(1);
sortedNumbers.add(2);
// 内部自动排序为 [1, 2, 3]

3. 静态成员和泛型

// 泛型类的静态成员
class Utility<T> {
    // 静态成员不能使用类的类型参数
    static createArray<U>(length: number, value: U): U[] {
        return new Array(length).fill(value);
    }
    
    // 实例成员可以使用类的类型参数
    process(item: T): T {
        return item;
    }
}

// 使用静态方法
let stringArray = Utility.createArray(3, "hello"); // ["hello", "hello", "hello"]
let numberArray = Utility.createArray(5, 0);       // [0, 0, 0, 0, 0]

4. 复杂的泛型类示例

// 事件发射器泛型类
type EventMap = Record<string, any>;

class EventEmitter<T extends EventMap> {
    private listeners: {
        [K in keyof T]?: Array<(data: T[K]) => void>;
    } = {};
    
    on<K extends keyof T>(event: K, listener: (data: T[K]) => void): void {
        if (!this.listeners[event]) {
            this.listeners[event] = [];
        }
        this.listeners[event]!.push(listener);
    }
    
    emit<K extends keyof T>(event: K, data: T[K]): void {
        const eventListeners = this.listeners[event];
        if (eventListeners) {
            eventListeners.forEach(listener => listener(data));
        }
    }
    
    off<K extends keyof T>(event: K, listener: (data: T[K]) => void): void {
        const eventListeners = this.listeners[event];
        if (eventListeners) {
            const index = eventListeners.indexOf(listener);
            if (index > -1) {
                eventListeners.splice(index, 1);
            }
        }
    }
}

// 定义事件类型
interface AppEvents {
    userLogin: { userId: number; username: string };
    userLogout: { userId: number };
    dataUpdate: { table: string; id: number };
}

// 使用类型安全的事件发射器
const appEmitter = new EventEmitter<AppEvents>();

appEmitter.on('userLogin', (data) => {
    // data 的类型是 { userId: number; username: string }
    console.log(`User ${data.username} logged in`);
});

appEmitter.emit('userLogin', { userId: 1, username: '张三' });

泛型约束

1. 基础泛型约束

// 约束泛型必须有 length 属性
interface Lengthwise {
    length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
    console.log(arg.length); // 现在可以访问 length 属性
    return arg;
}

// 使用
logLength("hello");        // ✅ 字符串有 length
logLength([1, 2, 3]);      // ✅ 数组有 length
logLength({ length: 10 }); // ✅ 对象有 length
// logLength(123);         // ❌ 数字没有 length

2. 使用类型参数约束

// 使用 keyof 约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

let person = { name: "张三", age: 30, city: "北京" };

let name = getProperty(person, "name");  // string
let age = getProperty(person, "age");    // number
// let invalid = getProperty(person, "salary"); // ❌ 'salary' 不存在于 person 中

// 更复杂的约束
function updateProperty<T, K extends keyof T>(
    obj: T, 
    key: K, 
    value: T[K]
): T {
    return { ...obj, [key]: value };
}

let updatedPerson = updateProperty(person, "age", 31); // 类型安全的更新

3. 条件约束

// 条件约束
type NonNullable<T> = T extends null | undefined ? never : T;

function processValue<T>(value: NonNullable<T>): T {
    // value 不会是 null 或 undefined
    return value as T;
}

// 约束为特定类型的子类型
interface Animal {
    name: string;
}

interface Dog extends Animal {
    breed: string;
}

interface Cat extends Animal {
    meow(): void;
}

function petName<T extends Animal>(pet: T): string {
    return pet.name; // 可以安全访问 name 属性
}

let dog: Dog = { name: "Buddy", breed: "Golden Retriever" };
let cat: Cat = { name: "Whiskers", meow: () => console.log("Meow!") };

console.log(petName(dog)); // "Buddy"
console.log(petName(cat)); // "Whiskers"

4. 多重约束

// 多重约束
interface Serializable {
    serialize(): string;
}

interface Timestamped {
    timestamp: Date;
}

function processData<T extends Serializable & Timestamped>(data: T): string {
    return `${data.timestamp.toISOString()}: ${data.serialize()}`;
}

// 实现多重约束的类
class LogEntry implements Serializable, Timestamped {
    constructor(
        public message: string,
        public timestamp: Date = new Date()
    ) {}
    
    serialize(): string {
        return JSON.stringify({
            message: this.message,
            timestamp: this.timestamp.toISOString()
        });
    }
}

let entry = new LogEntry("System started");
console.log(processData(entry));

5. 构造函数约束

// 约束为构造函数类型
interface Constructable {
    new (...args: any[]): any;
}

function createInstance<T extends Constructable>(
    constructor: T,
    ...args: any[]
): InstanceType<T> {
    return new constructor(...args);
}

class User {
    constructor(public name: string, public age: number) {}
}

class Product {
    constructor(public name: string, public price: number) {}
}

// 使用
let user = createInstance(User, "张三", 30);       // User 实例
let product = createInstance(Product, "手机", 999); // Product 实例

// 更具体的构造函数约束
interface UserConstructor {
    new (name: string, age: number): User;
}

function createUser<T extends UserConstructor>(
    UserClass: T,
    name: string,
    age: number
): InstanceType<T> {
    return new UserClass(name, age);
}

高级泛型模式

1. 条件类型

// 基础条件类型
type IsString<T> = T extends string ? true : false;

type Test1 = IsString<string>;  // true
type Test2 = IsString<number>;  // false

// 更复杂的条件类型
type ApiResponse<T> = T extends string 
    ? { message: T } 
    : T extends number 
    ? { code: T } 
    : { data: T };

type StringResponse = ApiResponse<string>; // { message: string }
type NumberResponse = ApiResponse<number>; // { code: number }
type ObjectResponse = ApiResponse<object>; // { data: object }

// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type StringOrNumberArray = ToArray<string | number>; // string[] | number[]

2. infer 关键字

// 推断返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getString(): string { return "hello"; }
function getNumber(): number { return 42; }

type StringReturn = ReturnType<typeof getString>; // string
type NumberReturn = ReturnType<typeof getNumber>; // number

// 推断参数类型
type Parameters<T> = T extends (...args: infer P) => any ? P : never;

function add(a: number, b: number): number { return a + b; }
type AddParams = Parameters<typeof add>; // [number, number]

// 推断数组元素类型
type ArrayElement<T> = T extends (infer U)[] ? U : never;
type StringElement = ArrayElement<string[]>; // string
type NumberElement = ArrayElement<number[]>; // number

// 推断 Promise 的值类型
type Awaited<T> = T extends Promise<infer U> ? U : T;
type PromiseString = Awaited<Promise<string>>; // string
type DirectString = Awaited<string>; // string

3. 递归类型

// 深度只读类型
type DeepReadonly<T> = {
    readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

interface User {
    name: string;
    profile: {
        age: number;
        address: {
            street: string;
            city: string;
        };
    };
}

type ReadonlyUser = DeepReadonly<User>;
// 所有属性都变成只读,包括嵌套对象

// 深度可选类型
type DeepPartial<T> = {
    [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

type PartialUser = DeepPartial<User>;
// 所有属性都变成可选,包括嵌套对象

// 路径类型
type Path<T> = T extends object 
    ? {
        [K in keyof T]: K extends string 
            ? T[K] extends object 
                ? `${K}` | `${K}.${Path<T[K]>}`
                : `${K}`
            : never
    }[keyof T]
    : never;

type UserPaths = Path<User>; 
// "name" | "profile" | "profile.age" | "profile.address" | "profile.address.street" | "profile.address.city"

4. 模板字面量类型

// 基础模板字面量类型
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"
type HoverEvent = EventName<"hover">; // "onHover"

// 组合模板字面量类型
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiPath = "users" | "products" | "orders";
type ApiEndpoint = `${HttpMethod} /api/${ApiPath}`;

// 结果类型:
// "GET /api/users" | "POST /api/users" | "PUT /api/users" | "DELETE /api/users" |
// "GET /api/products" | "POST /api/products" | "PUT /api/products" | "DELETE /api/products" |
// "GET /api/orders" | "POST /api/orders" | "PUT /api/orders" | "DELETE /api/orders"

// 解析模板字面量类型
type ParseApiEndpoint<T extends string> = 
    T extends `${infer Method} /api/${infer Path}` 
        ? { method: Method; path: Path }
        : never;

type ParsedEndpoint = ParseApiEndpoint<"GET /api/users">; 
// { method: "GET"; path: "users" }

// CSS 属性类型
type CSSProperty = 
    | "color" 
    | "background-color" 
    | "font-size" 
    | "margin" 
    | "padding";

type CSSVariableName<T extends CSSProperty> = `--${T}`;
type ColorVariable = CSSVariableName<"color">; // "--color"

映射类型

1. 基础映射类型

// 基础映射类型语法
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

type Partial<T> = {
    [P in keyof T]?: T[P];
};

type Required<T> = {
    [P in keyof T]-?: T[P];
};

// 使用示例
interface User {
    name: string;
    age?: number;
    email: string;
}

type ReadonlyUser = Readonly<User>;
// { readonly name: string; readonly age?: number; readonly email: string; }

type PartialUser = Partial<User>;
// { name?: string; age?: number; email?: string; }

type RequiredUser = Required<User>;
// { name: string; age: number; email: string; }

2. 键映射

// 键名转换
type Getters<T> = {
    [P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
};

type Setters<T> = {
    [P in keyof T as `set${Capitalize<string & P>}`]: (value: T[P]) => void;
};

interface Person {
    name: string;
    age: number;
}

type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number; }

type PersonSetters = Setters<Person>;
// { setName: (value: string) => void; setAge: (value: number) => void; }

// 过滤键
type PickByType<T, U> = {
    [P in keyof T as T[P] extends U ? P : never]: T[P];
};

interface Mixed {
    name: string;
    age: number;
    isActive: boolean;
    tags: string[];
}

type StringProperties = PickByType<Mixed, string>;
// { name: string; }

type NumberProperties = PickByType<Mixed, number>;
// { age: number; }

3. 条件映射

// 条件映射类型
type NullableProperties<T> = {
    [P in keyof T]: T[P] | null;
};

type OptionalNullable<T> = {
    [P in keyof T]?: T[P] | null;
};

interface User {
    id: number;
    name: string;
    email: string;
}

type NullableUser = NullableProperties<User>;
// { id: number | null; name: string | null; email: string | null; }

// 基于条件的属性转换
type StringifyProperties<T> = {
    [P in keyof T]: T[P] extends string ? T[P] : string;
};

interface Data {
    name: string;
    age: number;
    isActive: boolean;
}

type StringifiedData = StringifyProperties<Data>;
// { name: string; age: string; isActive: string; }

4. 递归映射类型

// 深度映射
type DeepNullable<T> = {
    [P in keyof T]: T[P] extends object ? DeepNullable<T[P]> : T[P] | null;
};

interface NestedData {
    user: {
        profile: {
            name: string;
            age: number;
        };
        settings: {
            theme: string;
            notifications: boolean;
        };
    };
    metadata: {
        version: string;
    };
}

type DeepNullableData = DeepNullable<NestedData>;
// 所有嵌套属性都变成可为 null

// 深度转换类型
type DeepStringify<T> = {
    [P in keyof T]: T[P] extends object 
        ? DeepStringify<T[P]> 
        : string;
};

type StringifiedNestedData = DeepStringify<NestedData>;
// 所有最终属性都变成 string 类型

实用工具类型

1. TypeScript 内置工具类型

// Partial<T> - 使所有属性可选
interface User {
    id: number;
    name: string;
    email: string;
    age: number;
}

type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; age?: number; }

function updateUser(user: User, updates: Partial<User>): User {
    return { ...user, ...updates };
}

// Required<T> - 使所有属性必需
interface Config {
    apiUrl?: string;
    timeout?: number;
    retries?: number;
}

type RequiredConfig = Required<Config>;
// { apiUrl: string; timeout: number; retries: number; }

// Readonly<T> - 使所有属性只读
type ReadonlyUser = Readonly<User>;
// { readonly id: number; readonly name: string; readonly email: string; readonly age: number; }

// Pick<T, K> - 选择特定属性
type UserSummary = Pick<User, 'id' | 'name'>;
// { id: number; name: string; }

// Omit<T, K> - 排除特定属性
type UserWithoutId = Omit<User, 'id'>;
// { name: string; email: string; age: number; }

// Record<K, T> - 创建键值对类型
type UserRoles = Record<string, string[]>;
// { [key: string]: string[]; }

let roles: UserRoles = {
    "admin": ["read", "write", "delete"],
    "user": ["read"],
    "guest": []
};

2. 函数相关工具类型

// ReturnType<T> - 获取函数返回类型
function getUser(): User {
    return { id: 1, name: "张三", email: "zhangsan@example.com", age: 30 };
}

type GetUserReturn = ReturnType<typeof getUser>; // User

// Parameters<T> - 获取函数参数类型
function createUser(name: string, age: number, email: string): User {
    return { id: Date.now(), name, age, email };
}

type CreateUserParams = Parameters<typeof createUser>; // [string, number, string]

// ConstructorParameters<T> - 获取构造函数参数类型
class UserService {
    constructor(private apiUrl: string, private timeout: number) {}
}

type UserServiceParams = ConstructorParameters<typeof UserService>; // [string, number]

// InstanceType<T> - 获取构造函数实例类型
type UserServiceInstance = InstanceType<typeof UserService>; // UserService

3. 字符串操作工具类型

// Uppercase<T> - 转大写
type UppercaseHello = Uppercase<"hello">; // "HELLO"

// Lowercase<T> - 转小写
type LowercaseHELLO = Lowercase<"HELLO">; // "hello"

// Capitalize<T> - 首字母大写
type CapitalizeHello = Capitalize<"hello">; // "Hello"

// Uncapitalize<T> - 首字母小写
type UncapitalizeHello = Uncapitalize<"Hello">; // "hello"

// 实际应用
type HttpMethod = "get" | "post" | "put" | "delete";
type UppercaseMethod = Uppercase<HttpMethod>; // "GET" | "POST" | "PUT" | "DELETE"

type EventName<T extends string> = `on${Capitalize<T>}`;
type Events = EventName<"click" | "hover" | "focus">; // "onClick" | "onHover" | "onFocus"

4. 自定义工具类型

// NonNullable<T> - 排除 null 和 undefined
type NonNullable<T> = T extends null | undefined ? never : T;
type NonNullableString = NonNullable<string | null | undefined>; // string

// Exclude<T, U> - 从 T 中排除 U
type Exclude<T, U> = T extends U ? never : T;
type WithoutString = Exclude<string | number | boolean, string>; // number | boolean

// Extract<T, U> - 从 T 中提取 U
type Extract<T, U> = T extends U ? T : never;
type OnlyString = Extract<string | number | boolean, string>; // string

// 自定义工具类型
type DeepRequired<T> = {
    [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};

type ValueOf<T> = T[keyof T];

interface Colors {
    red: "#ff0000";
    green: "#00ff00";
    blue: "#0000ff";
}

type ColorValue = ValueOf<Colors>; // "#ff0000" | "#00ff00" | "#0000ff"

// 函数重载工具类型
type Overload<T> = T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3;
} ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3
] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
} ? [
    (...args: A1) => R1,
    (...args: A2) => R2
] : T extends (...args: infer A) => infer R ? [(...args: A) => R] : never;

实战案例

1. 类型安全的状态管理

// 状态管理系统
interface State {
    user: {
        id: number;
        name: string;
        email: string;
    } | null;
    posts: Array<{
        id: number;
        title: string;
        content: string;
        authorId: number;
    }>;
    loading: {
        user: boolean;
        posts: boolean;
    };
}

// 动作类型
type Action<T extends keyof State> = {
    type: `SET_${Uppercase<string & T>}`;
    payload: State[T];
} | {
    type: `UPDATE_${Uppercase<string & T>}`;
    payload: Partial<State[T]>;
};

// 生成所有可能的动作
type UserAction = Action<'user'>;
type PostsAction = Action<'posts'>;
type LoadingAction = Action<'loading'>;

type AllActions = UserAction | PostsAction | LoadingAction;

// 状态管理器
class StateManager<T extends Record<string, any>> {
    private state: T;
    private listeners: Array<(state: T) => void> = [];
    
    constructor(initialState: T) {
        this.state = initialState;
    }
    
    getState(): T {
        return { ...this.state };
    }
    
    setState<K extends keyof T>(key: K, value: T[K]): void {
        this.state = { ...this.state, [key]: value };
        this.notifyListeners();
    }
    
    updateState<K extends keyof T>(key: K, updates: Partial<T[K]>): void {
        this.state = {
            ...this.state,
            [key]: { ...this.state[key], ...updates }
        };
        this.notifyListeners();
    }
    
    subscribe(listener: (state: T) => void): () => void {
        this.listeners.push(listener);
        return () => {
            const index = this.listeners.indexOf(listener);
            if (index > -1) {
                this.listeners.splice(index, 1);
            }
        };
    }
    
    private notifyListeners(): void {
        this.listeners.forEach(listener => listener(this.state));
    }
}

// 使用
const stateManager = new StateManager<State>({
    user: null,
    posts: [],
    loading: { user: false, posts: false }
});

// 类型安全的状态更新
stateManager.setState('user', { id: 1, name: '张三', email: 'zhangsan@example.com' });
stateManager.updateState('loading', { user: true });

2. 类型安全的 API 客户端

// API 端点定义
interface ApiEndpoints {
    'GET /users': {
        params: { page?: number; limit?: number };
        response: { users: User[]; total: number };
    };
    'GET /users/:id': {
        params: { id: number };
        response: User;
    };
    'POST /users': {
        body: Omit<User, 'id'>;
        response: User;
    };
    'PUT /users/:id': {
        params: { id: number };
        body: Partial<Omit<User, 'id'>>;
        response: User;
    };
    'DELETE /users/:id': {
        params: { id: number };
        response: { success: boolean };
    };
}

// 提取路径参数
type ExtractParams<T extends string> = 
    T extends `${infer _Start}:${infer Param}/${infer Rest}`
        ? { [K in Param]: string | number } & ExtractParams<`/${Rest}`>
        : T extends `${infer _Start}:${infer Param}`
        ? { [K in Param]: string | number }
        : {};

// API 客户端
class ApiClient {
    constructor(private baseUrl: string) {}
    
    async request<T extends keyof ApiEndpoints>(
        endpoint: T,
        options: ApiEndpoints[T] extends { params: infer P }
            ? ApiEndpoints[T] extends { body: infer B }
                ? { params: P; body: B }
                : { params: P }
            : ApiEndpoints[T] extends { body: infer B }
            ? { body: B }
            : {}
    ): Promise<ApiEndpoints[T]['response']> {
        // 实现 API 调用逻辑
        const [method, path] = (endpoint as string).split(' ');
        
        // 构建 URL
        let url = this.baseUrl + path;
        if ('params' in options) {
            // 替换路径参数
            Object.entries(options.params as Record<string, any>).forEach(([key, value]) => {
                url = url.replace(`:${key}`, String(value));
            });
        }
        
        // 发送请求
        const response = await fetch(url, {
            method,
            headers: {
                'Content-Type': 'application/json',
            },
            body: 'body' in options ? JSON.stringify(options.body) : undefined,
        });
        
        return response.json();
    }
}

// 使用示例
const apiClient = new ApiClient('https://api.example.com');

// 类型安全的 API 调用
async function example() {
    // GET 请求
    const users = await apiClient.request('GET /users', {
        params: { page: 1, limit: 10 }
    });
    
    // GET 单个用户
    const user = await apiClient.request('GET /users/:id', {
        params: { id: 1 }
    });
    
    // POST 创建用户
    const newUser = await apiClient.request('POST /users', {
        body: { name: '张三', email: 'zhangsan@example.com', age: 30 }
    });
    
    // PUT 更新用户
    const updatedUser = await apiClient.request('PUT /users/:id', {
        params: { id: 1 },
        body: { name: '李四' }
    });
    
    // DELETE 删除用户
    const deleteResult = await apiClient.request('DELETE /users/:id', {
        params: { id: 1 }
    });
}

3. 类型安全的表单验证

// 验证规则类型
type ValidationRule<T> = {
    required?: boolean;
    minLength?: number;
    maxLength?: number;
    pattern?: RegExp;
    custom?: (value: T) => string | null;
};

type ValidationRules<T> = {
    [K in keyof T]?: ValidationRule<T[K]>;
};

type ValidationErrors<T> = {
    [K in keyof T]?: string;
};

// 表单验证器
class FormValidator<T extends Record<string, any>> {
    private rules: ValidationRules<T>;
    
    constructor(rules: ValidationRules<T>) {
        this.rules = rules;
    }
    
    validate(data: T): ValidationErrors<T> {
        const errors: ValidationErrors<T> = {};
        
        for (const key in this.rules) {
            const rule = this.rules[key];
            const value = data[key];
            
            if (rule) {
                const error = this.validateField(key, value, rule);
                if (error) {
                    errors[key] = error;
                }
            }
        }
        
        return errors;
    }
    
    private validateField<K extends keyof T>(
        key: K,
        value: T[K],
        rule: ValidationRule<T[K]>
    ): string | null {
        if (rule.required && (value === undefined || value === null || value === '')) {
            return `${String(key)} 是必填项`;
        }
        
        if (typeof value === 'string') {
            if (rule.minLength && value.length < rule.minLength) {
                return `${String(key)} 最少需要 ${rule.minLength} 个字符`;
            }
            
            if (rule.maxLength && value.length > rule.maxLength) {
                return `${String(key)} 最多只能有 ${rule.maxLength} 个字符`;
            }
            
            if (rule.pattern && !rule.pattern.test(value)) {
                return `${String(key)} 格式不正确`;
            }
        }
        
        if (rule.custom) {
            return rule.custom(value);
        }
        
        return null;
    }
    
    isValid(data: T): boolean {
        const errors = this.validate(data);
        return Object.keys(errors).length === 0;
    }
}

// 使用示例
interface UserForm {
    username: string;
    email: string;
    password: string;
    confirmPassword: string;
    age: number;
}

const userFormValidator = new FormValidator<UserForm>({
    username: {
        required: true,
        minLength: 3,
        maxLength: 20,
        pattern: /^[a-zA-Z0-9_]+$/
    },
    email: {
        required: true,
        pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    },
    password: {
        required: true,
        minLength: 8,
        custom: (value) => {
            if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
                return '密码必须包含大小写字母和数字';
            }
            return null;
        }
    },
    confirmPassword: {
        required: true,
        custom: (value) => {
            // 注意:这里需要访问其他字段,实际实现可能需要调整
            return null;
        }
    },
    age: {
        required: true,
        custom: (value) => {
            if (value < 18 || value > 120) {
                return '年龄必须在 18-120 之间';
            }
            return null;
        }
    }
});

// 验证表单
const formData: UserForm = {
    username: 'john_doe',
    email: 'john@example.com',
    password: 'Password123',
    confirmPassword: 'Password123',
    age: 25
};

const errors = userFormValidator.validate(formData);
const isValid = userFormValidator.isValid(formData);

console.log('验证错误:', errors);
console.log('表单有效:', isValid);

总结

泛型是 TypeScript 中最强大和最重要的特性之一。通过本文的深入学习,您应该掌握了:

核心概念

  1. 泛型函数:创建可重用的类型安全函数
  2. 泛型接口:定义灵活的数据结构契约
  3. 泛型类:构建可重用的类型安全类
  4. 泛型约束:限制泛型参数的类型范围

高级特性

  1. 条件类型:基于条件的类型选择
  2. 映射类型:转换现有类型的结构
  3. 模板字面量类型:类型级别的字符串操作
  4. 递归类型:处理深层嵌套结构

实用工具

  1. 内置工具类型:Partial、Required、Pick、Omit 等
  2. 自定义工具类型:根据需求创建专用类型
  3. 类型推断:使用 infer 关键字进行类型推断

最佳实践

  1. 渐进式采用:从简单的泛型开始,逐步使用高级特性
  2. 类型约束:合理使用约束确保类型安全
  3. 可读性:保持类型定义的清晰和可理解
  4. 性能考虑:避免过度复杂的类型计算

掌握泛型将大大提升您的 TypeScript 编程能力,使您能够编写更加类型安全、可维护和可重用的代码。在实际项目中,建议从基础泛型开始应用,随着经验的积累逐步使用更高级的特性。