目录

TypeScript高级类型编程

TypeScript 的类型系统是图灵完备的,掌握高级类型编程能让你写出更安全、更优雅的代码。

条件类型

条件类型类似于三元表达式,根据类型关系选择不同分支:

typescript
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false

分布式条件类型

当 T 是联合类型时,条件类型会分布执行:

typescript
type ToArray<T> = T extends any ? T[] : never;

type Result = ToArray<string | number>;
// string[] | number[]

infer 关键字

infer 用于在条件类型中提取类型变量:

typescript
// 提取函数返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

// 提取 Promise 内部类型
type Unpacked<T> = T extends Promise<infer U> ? U : T;

type R = Unpacked<Promise<string>>;  // string

映射类型

映射类型可以根据现有类型创建新类型:

typescript
// 将所有属性变为只读
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

// 将所有属性变为可选
type Partial<T> = {
  [P in keyof T]?: T[P];
};

// 将所有属性变为可空
type Nullable<T> = {
  [P in keyof T]: T[P] | null;
};

模板字面量类型

TypeScript 4.1 引入了模板字面量类型:

typescript
type EventName = `on${Capitalize<string>}`;

// 创建 getter 方法名
type Getter<T> = {
  [P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
};

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

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

内置工具类型

工具类型 作用
Partial<T> 所有属性可选
Required<T> 所有属性必填
Pick<T, K> 选取部分属性
Omit<T, K> 排除部分属性
Record<K, V> 构建键值对类型
ReturnType<T> 获取函数返回类型
Parameters<T> 获取函数参数类型

实战:类型安全的路由

typescript
type Routes = '/home' | '/about' | '/user/:id';

type RouteParams<T extends string> =
  T extends `${string}:${infer Param}`
    ? { [K in Param]: string }
    : {};

function navigate<T extends Routes>(route: T, params: RouteParams<T>) {
  // 实现...
}

// 类型安全!参数必须匹配路由
navigate('/home', {});
navigate('/user/:id', { id: '123' });

总结

TypeScript 高级类型编程虽然学习曲线陡峭,但它能帮你在编译时捕获大量错误。条件类型、infer 和映射类型是三大核心武器,熟练运用后能让你的代码类型安全性大幅提升。