前言

💡 痛点:看不懂复杂的泛型约束?写不出高级类型工具?TypeScript 类型系统深似海?

🎯 解决方案:从条件类型映射类型,从模板字面量递归类型,手把手教你玩转 TypeScript 类型系统。

为什么要深入 TypeScript 类型系统?

TypeScript 类型系统

基础类型

泛型

高级类型

🎯 类型安全

⚡ 代码提示

🛡️ 运行时检查前置

本文目标: 让你从"会用 TypeScript"到"精通类型系统、写出优雅类型工具"。


一、条件类型基础

1.1 条件类型语法

// ===== 条件类型基础 =====

// 语法:T extends U ? X : Y
// 如果 T 是 U 的子类型,返回 X,否则返回 Y

// 基础示例
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false
type C = IsString<"hello">; // true(字面量是 string 子类型)

// 泛型条件类型
type ExtractArray<T> = T extends any[] ? T : never;

type D = ExtractArray<string[]>;  // string[]
type E = ExtractArray<number>;    // never
type F = ExtractArray<string>;     // never

// never 是底类型,表示"无任何类型"
type G = ExtractArray<any[]>;      // any[]

1.2 分布条件类型

// ===== 分布条件类型 =====

// 条件类型在联合类型上是"分布式"的
type ToArray<T> = T extends any ? T[] : never;

type H = ToArray<string | number>;
// 分布计算:(string extends any ? string[] : never) | (number extends any ? number[] : never)
// 结果:string[] | number[]

type I = ToArray<"a" | "b" | "c">;
// 结果:("a")[] | ("b")[] | ("c")[]
// 即:"a"[] | "b"[] | "c"[]

// 如果不想分布,使用元组包装
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;

type J = ToArrayNonDist<string | number>;
// 结果:(string | number)[](不分布)

// ===== 常用工具类型的条件类型实现 =====

// 实现 Awaited<T>
type Awaited<T> = 
  T extends null | undefined ? T :
  T extends object & { then: infer F } ? 
    F extends (value: infer V, ...args: any) ? Awaited<V> :
    never :
  T;

// 测试
type K = Awaited<Promise<string>>;         // string
type L = Awaited<Promise<Promise<number>>>; // number
type M = Awaited<"hello">;                  // "hello"

1.3 条件类型与 infer

// ===== infer 关键字 =====

// infer 用于在条件类型中提取类型

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

type N = ReturnType<() => string>;           // string
type O = ReturnType<(x: number) => boolean>; // boolean
type P = ReturnType<() => Promise<number>>;  // Promise<number>

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

type Q = Parameters<(name: string, age: number) => void>;  // [string, number]
type R = Parameters<(x: number) => boolean>;              // [number]

// 提取构造函数参数
type ConstructorParameters<T> = 
  T extends new (...args: infer P) => any ? P : never;

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

type S = ConstructorParameters<typeof Person>;  // [string, number]

// 提取数组元素类型
type ElementType<T> = T extends (infer E)[] ? E : never;

type T_array = ElementType<string[]>;    // string
type U_array = ElementType<number[]>;    // number
type V_array = ElementType<(string | number)[]>;  // string | number

// 提取 Promise resolve 类型
type UnwrapPromise<T> = T extends Promise<infer V> ? V : T;

type W = UnwrapPromise<Promise<string>>; // string
type X = UnwrapPromise<number>;          // number

二、映射类型

2.1 基础映射类型

// ===== 基础映射类型 =====

// 语法:{ [K in keyof T]: ... }
type Person = {
  name: string;
  age: number;
  email: string;
};

// 将所有属性转为可选
type Partial<T> = { [K in keyof T]?: T[K] };
type PartialPerson = Partial<Person>;
// { name?: string; age?: number; email?: string; }

// 将所有属性转为必填
type Required<T> = { [K in keyof T]-?: T[K] };
type RequiredPerson = Required<PartialPerson>;  // 回到 Person

// 将所有属性转为只读
type Readonly<T> = { readonly [K in keyof T]: T[K] };
type ReadonlyPerson = Readonly<Person>;
// { readonly name: string; readonly age: number; readonly email: string; }

// 提取特定属性
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
type PersonName = Pick<Person, "name">;
// { name: string; }

// 排除特定属性
type Omit<T, K extends keyof T> = { [P in Exclude<keyof T, K>]: T[P] };
type PersonWithoutAge = Omit<Person, "age">;
// { name: string; email: string; }

2.2 映射类型修饰符

// ===== 映射类型修饰符 =====

// -?: 移除可选修饰符
// +?: 添加可选修饰符
// readonly: 添加只读修饰符
// -readonly: 移除只读修饰符

type CreateOptional<T> = { [K in keyof T]?: T[K] };
type CreateReadonly<T> = { readonly [K in keyof T]: T[K] };

// 条件映射:只映射满足条件的属性
type PickByValue<T, V> = {
  [K in keyof T as T[K] extends V ? K : never]: T[K];
};

type Mixed = { name: string; age: number; active: boolean };
type StringProps = PickByValue<Mixed, string>;  // { name: string }

// ===== 使用 as 重映射键 =====

// TypeScript 4.1+ 支持
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

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

// 移除某属性
type RemoveProperty<T, K extends keyof T> = {
  [P in keyof T as P extends K ? never : P]: T[P];
};

// 条件添加属性
type MaybeNull<T> = T extends object ? T & { null: null } : never;

2.3 映射类型进阶

// ===== 映射类型进阶 =====

// 根据键值类型映射
type MapValues<T, V> = {
  [K in keyof T]: V;
};

type StringRecord = MapValues<{ a: number; b: string }, boolean>;
// { a: boolean; b: boolean }

// 递归映射
type DeepReadonly<T> = 
  T extends object 
    ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
    : T;

type Nested = { user: { profile: { name: string } } };
type DeepReadonlyNested = DeepReadonly<Nested>;
// { readonly user: { readonly profile: { readonly name: string } } }

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

// ===== 使用模板字面量映射键 =====

type EventHandlers<T> = {
  [K in keyof T as `on${Capitalize<string & K>}Change`]: (value: T[K]) => void;
};

type State = { count: number; name: string };
type Handlers = EventHandlers<State>;
// { onCountChange: (value: number) => void; onNameChange: (value: string) => void; }

// 键值对互换
type Flip<T> = {
  [K in keyof T as T[K] extends string | number ? T[K] : never]: K
};

type Status = { pending: "pending"; active: "active"; done: "done" };
type Flipped = Flip<Status>;
// { pending: "pending"; active: "active"; done: "done" }
// 实际效果:值变成键,键变成值

三、模板字面量类型

3.1 基础模板字面量

// ===== 基础模板字面量类型 =====

type World = "world";
type Greeting = `hello, ${World}`;  // "hello, world"

// 连接字符串
type Email = `${string}@${string}.${string}`;
const validEmail: Email = "user@example.com";
// const invalidEmail: Email = "not-an-email"; // ❌ 错误

// 使用泛型
type SuccessMessage<T> = `Success: ${T}`;
type ErrorMessage<T> = `Error: ${T}`;

type A = SuccessMessage<"User created">;  // "Success: User created"
type B = ErrorMessage<"Not found">;       // "Error: Not found"

// 联合类型组合
type Direction = "top" | "right" | "bottom" | "left";
type EventName = `on${Capitalize<Direction>}`;
type Events = { [K in EventName]: () => void };
// { onTop: () => void; onRight: () => void; onBottom: () => void; onLeft: () => void; }

3.2 模板字面量与映射类型

// ===== 模板字面量与映射类型 =====

// 自动生成 getter/setter
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

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

type Model = { name: string; age: number };
type ModelGetters = Getters<Model>;
// { getName: () => string; getAge: () => number; }
type ModelSetters = Setters<Model>;
// { setName: (value: string) => void; setAge: (value: number) => void; }

// 组合 getter 和 setter
type Accessors<T> = Getters<T> & Setters<T>;
type ModelAccessors = Accessors<Model>;
// { getName: () => string; setName: (value: string) => void; ... }

// ===== 字符串操作类型 =====

// Uppercase, Lowercase, Capitalize, Uncapitalize
type A1 = Uppercase<"hello">;     // "HELLO"
type A2 = Lowercase<"WORLD">;     // "world"
type A3 = Capitalize<"hello">;    // "Hello"
type A4 = Uncapitalize<"Hello">;  // "hello"

// 递归字符串处理
type Split<S extends string, D extends string = ""> = 
  S extends `${infer Head}${D}${infer Tail}` 
    ? [Head, ...Split<Tail, D>] 
    : S extends "" ? [] : [S];

type B1 = Split<"a-b-c", "-">;   // ["a", "b", "c"]
type B2 = Split<"hello world", " ">;  // ["hello", "world"]

type Join<T extends string[], D extends string = ""> = 
  T extends [] ? "" :
  T extends [infer F extends string, ...infer R extends string[]] 
    ? F extends "" ? Join<R, D> : `${F}${D}${Join<R, D>}` : "";

type C1 = Join<["a", "b", "c"], "-">;  // "a-b-c"
type C2 = Join<["hello", "world"], " ">  // "hello world"

3.3 实际应用场景

// ===== 模板字面量实际应用 =====

// 1. CSS-in-JS 类型
type CSSProperties = {
  [K in `css\${string}`]?: string | number;
};

const styles: CSSProperties = {
  cssColor: "red",
  cssFontSize: "14px",
  cssMarginTop: 10,
};

// 2. 事件系统类型
type EventMap = {
  click: { x: number; y: number };
  keydown: { key: string };
  resize: { width: number; height: number };
};

type EventHandler<K extends keyof EventMap> = (event: EventMap[K]) => void;

function addEventListener<K extends keyof EventMap>(
  event: K,
  handler: EventHandler<K>
): void {
  // 实现...
}

// 3. API 路由类型
type Routes = {
  "/users": { id: string; name: string };
  "/posts": { id: string; title: string };
};

type Handler<M extends keyof Routes> = (data: Routes[M]) => void;

function registerRoute<M extends keyof Routes>(
  path: M,
  handler: Handler<M>
): void {
  // 实现...
}

// 4. GraphQL 类型
type FieldSelection<T> = {
  [K in keyof T]?: boolean | FieldSelection<T[K]>
};

type UserSelection = FieldSelection<{
  id: string;
  name: string;
  email: string;
  profile: { avatar: string }
}>;
// { id?: boolean; name?: boolean; email?: boolean; profile?: FieldSelection<{ avatar: string }> }

四、递归类型

4.1 递归基础

// ===== 递归类型基础 =====

// 树形结构
interface TreeNode<T> {
  value: T;
  children: TreeNode<T>[];
}

// JSON 类型
type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };

// 深度递归类型
type DeepRequired<T> = T extends object 
  ? { [K in keyof T]-?: DeepRequired<T[K]> }
  : T;

type DeepPartial<T> = T extends object 
  ? { [K in keyof T]?: DeepPartial<T[K]> }
  : T;

type DeepReadonly<T> = T extends object 
  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
  : T;

// 测试
type Config = {
  server: {
    host: string;
    port: number;
  };
  database: {
    connection: {
      url: string;
      pool: number;
    };
  };
};

type DeepRequiredConfig = DeepRequired<Config>;
// 所有嵌套属性都变成必填

type DeepPartialConfig = DeepPartial<Config>;
// 所有嵌套属性都变成可选

4.2 列表操作

// ===== 列表操作类型 =====

// 不可变列表操作

// Head - 获取列表第一个元素
type Head<T extends any[]> = T extends [infer H, ...any[]] ? H : never;
type H1 = Head<[1, 2, 3]>;    // 1
type H2 = Head<string[]>;     // string

// Tail - 获取列表除第一个外的元素
type Tail<T extends any[]> = T extends [any, ...infer TAIL] ? TAIL : never;
type T1 = Tail<[1, 2, 3]>;   // [2, 3]
type T2 = Tail<string[]>;     // string[]

// Last - 获取列表最后一个元素
type Last<T extends any[]> = T extends [...any[], infer L] ? L : never;
type L1 = Last<[1, 2, 3]>;   // 3
type L2 = Last<string[]>;     // string

// Prepend - 在列表开头添加元素
type Prepend<T extends any[], V> = [V, ...T];
type P1 = Prepend<[2, 3], 1>;       // [1, 2, 3]
type P2 = Prepend<string[], number>;  // [number, ...string[]]

// Append - 在列表末尾添加元素
type Append<T extends any[], V> = [...T, V];
type A1 = Append<[1, 2], 3>;         // [1, 2, 3]

// Concat - 连接两个列表
type Concat<T extends any[], U extends any[]> = [...T, ...U];
type C1 = Concat<[1, 2], [3, 4]>;    // [1, 2, 3, 4]

// Reverse - 反转列表
type Reverse<T extends any[], R extends any[] = []> = 
  T extends [infer H, ...infer TAIL] 
    ? Reverse<TAIL, [H, ...R]> 
    : R;
type R1 = Reverse<[1, 2, 3]>;   // [3, 2, 1]

// Flatten - 展平嵌套列表
type Flatten<T extends any[]> = 
  T extends [infer H, ...infer TAIL] 
    ? H extends any[] 
      ? [...Flatten<H>, ...Flatten<TAIL>] 
      : [H, ...Flatten<TAIL>] 
    : [];
type F1 = Flatten<[1, [2, 3], [4, [5, 6]]]>;  // [1, 2, 3, 4, 5, 6]

4.3 路径与访问

// ===== 路径访问类型 =====

// 深层属性访问
type DeepGet<T, Path extends string> = 
  Path extends `${infer K}.${infer Rest}`
    ? K extends keyof T 
      ? DeepGet<T[K], Rest> 
      : never
    : Path extends keyof T 
      ? T[Path] 
      : never;

interface User {
  profile: {
    address: {
      city: string;
      zip: string;
    };
  };
  settings: {
    theme: string;
  };
}

type City = DeepGet<User, "profile.address.city">;  // string
type Theme = DeepGet<User, "settings.theme">;      // string

// 可选路径访问
type DeepGetOptional<T, Path extends string> = 
  Path extends `${infer K}.${infer Rest}`
    ? K extends keyof T 
      ? DeepGetOptional<T[K], Rest> 
      : undefined
    : Path extends keyof T 
      ? T[Path] 
      : undefined;

// ===== 路径设置类型 =====

// 设置深层属性
type DeepSet<T, Path extends string, Value> = 
  Path extends `${infer K}.${infer Rest}`
    ? K extends keyof T
      ? { [P in K]: DeepSet<T[K], Rest, Value> } & Omit<T, K>
      : never
    : Path extends keyof T
      ? { [P in keyof T]: P extends Path ? Value : T[P] }
      : never;

type UpdatedUser = DeepSet<User, "profile.address.city", "Beijing">;
// { profile: { address: { city: "Beijing"; zip: string }; }; settings: { theme: string; } }

// 深度合并
type DeepMerge<T, U> = 
  T extends object 
    ? U extends object 
      ? { [K in keyof (T & U)]: 
          K extends keyof T 
            ? K extends keyof U 
              ? DeepMerge<T[K], U[K]> 
              : T[K] 
            : K extends keyof U 
              ? U[K] 
              : never 
        }
      : U
    : U;

type X = DeepMerge<{ a: { x: number } }, { a: { y: string } }>;
// { a: { x: number; y: string } }

五、分配与高阶类型

5.1 类型分配

// ===== 类型分配 =====

// Union 分配
type ToString<T> = T extends any ? `${T}` : never;

type S1 = ToString<string | number | boolean>;
// 分配结果:"string" | "number" | "boolean"

type S2 = ToString<"a" | "b">;
// "a" | "b"

// ===== Filter Union =====

// 从 Union 中提取特定类型
type ExtractType<T, U> = T extends U ? T : never;

type Mixed = string | number | boolean;
type Strings = ExtractType<Mixed, string>;   // string
type Numbers = ExtractType<Mixed, number>;  // number

// ===== Exclude 简化实现 =====

type Exclude<T, U> = T extends U ? never : T;
type StringsOnly = Exclude<"a" | 1 | "b" | 2, number>;  // "a" | "b"

// ===== 递归 Union 处理 =====

// Union 转 Intersection
type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

type I1 = UnionToIntersection<string | number>;
// string & number = never(简单类型无法交叉)

type I2 = UnionToIntersection<{ a: string } | { b: number }>;
// { a: string } & { b: number }

5.2 高阶类型工厂

// ===== 高阶类型工厂 =====

// 类型柯里化
type Curried<T> = 
  T extends (...args: infer Args) => infer R
    ? Args extends [infer A, ...infer Rest]
      ? (arg: A) => Curried<(...args: Rest) => R>
      : () => R
    : never;

type Add = (a: number, b: number) => number;
type CurriedAdd = Curried<Add>;
// (a: number) => (b: number) => number

type ThreeArgs = (a: number, b: string, c: boolean) => void;
type CurriedThree = Curried<ThreeArgs>;
// (a: number) => (b: string) => (c: boolean) => void

// ===== 类型组合器 =====

// Or 类型
type Or<A extends boolean, B extends boolean> = A extends true ? true : B;

// And 类型
type And<A extends boolean, B extends boolean> = A extends true ? B : false;

// Not 类型
type Not<T extends boolean> = T extends true ? false : true;

// Xor 类型(异或)
type Xor<A extends boolean, B extends boolean> = 
  [A, B] extends [true, true] ? false :
  [A, B] extends [false, false] ? false :
  true;

// 测试
type T1 = Or<true, false>;   // true
type T2 = And<true, true>;  // true
type T3 = Not<true>;        // false
type T4 = Xor<true, false>; // true

六、实用类型工具集

6.1 常见工具类型实现

// ===== 常用工具类型实现 =====

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

// Required<T> - 将所有属性变为必填
type MyRequired<T> = { [P in keyof T]-?: T[P] };

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

// Pick<T, K> - 提取属性
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };

// Omit<T, K> - 排除属性
type MyOmit<T, K extends keyof T> = { [P in Exclude<keyof T, K>]: T[P] };

// Record<K, V> - 创建键值类型
type MyRecord<K extends keyof any, V> = { [P in K]: V };

// Exclude<T, U> - 排除类型
type MyExclude<T, U> = T extends U ? never : T;

// Extract<T, U> - 提取类型
type MyExtract<T, U> = T extends U ? T : never;

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

// ReturnType<T> - 获取函数返回值类型
type MyReturnType<T extends (...args: any) => any> = 
  T extends (...args: any) => infer R ? R : never;

// Parameters<T> - 获取函数参数类型
type MyParameters<T extends (...args: any) => any> = 
  T extends (...args: infer P) => any ? P : never;

// ConstructorParameters<T> - 获取构造函数参数
type MyConstructorParameters<T extends new (...args: any) => any> = 
  T extends new (...args: infer P) => any ? P : never;

// InstanceType<T> - 获取实例类型
type MyInstanceType<T extends new (...args: any) => any> = 
  T extends new (...args: any) => infer I ? I : never;

6.2 高级工具类型

// ===== 高级工具类型 =====

// Mutable<T> - 移除只读
type Mutable<T> = { -readonly [P in keyof T]: T[P] };

// DeepMutable<T> - 递归移除只读
type DeepMutable<T> = T extends object
  ? { -readonly [P in keyof T]: DeepMutable<T[P]> }
  : T;

// RequiredKeys<T> - 获取必填键
type RequiredKeys<T> = {
  [K in keyof T]-?: undefined extends T[K] ? never : K
}[keyof T];

// OptionalKeys<T> - 获取可选键
type OptionalKeys<T> = {
  [K in keyof T]-?: undefined extends T[K] ? K : never
}[keyof T];

// UnionToTuple<T> - Union 转 Tuple
type UnionToTuple<T> = 
  ([T] extends [never] ? [] : 
    ((T extends any ? (t: T) => T : never) extends (t: infer U) ? [U] : never));

type T1 = UnionToTuple<"a" | "b" | "c">;  // ["a", "b", "c"]

// IsNever<T> - 判断是否为 never
type IsNever<T> = [T] extends [never] ? true : false;

type N1 = IsNever<never>;  // true
type N2 = IsNever<string>; // false

// IsAny<T> - 判断是否为 any
type IsAny<T> = 0 extends (1 & T) ? true : false;

type A1 = IsAny<any>;     // true
type A2 = IsAny<string>;  // false

// IsEqual<T, U> - 判断类型是否相等
type IsEqual<A, B> = 
  (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) 
    ? true : false;

type E1 = IsEqual<string, string>;     // true
type E2 = IsEqual<string, number>;     // false

6.3 函数类型工具

// ===== 函数类型工具 =====

// PartialApply - 部分应用
type PartialApply<F, A extends keyof Parameters<F>> = 
  (...args: { [K in A]: Parameters<F>[K] }) => ReturnType<F>;

// Overload - 函数重载类型
type Overload<F extends any[], R> = {
  (...args: F): R;
};

// Callable - 检测可调用
type Callable<T> = T extends (...args: any[]) => any ? true : false;

// 安全的参数替换
type ReplaceFirst<T extends any[], A, B> = 
  T extends [infer First, ...infer Rest] 
    ? First extends A ? [B, ...Rest] : [First, ...ReplaceFirst<Rest, A, B>]
    : T;

// 测试
type R1 = ReplaceFirst<[string, number, boolean], string, Date>;
// [Date, number, boolean]

// 延迟类型计算
type Deferred<T> = T | (() => T);

type ResolveDeferred<T> = T extends () => infer R ? R : T;

七、实战案例

7.1 表单验证类型

// ===== 表单验证类型系统 =====

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

// 表单字段类型
interface FormField<T> {
  value: T;
  rules: ValidationRule<T>[];
  error?: string;
  touched: boolean;
}

// 验证器函数
type Validator<T> = {
  [K in keyof T]: FormField<T[K]>;
};

// 验证表单
function validateForm<T>(form: Validator<T>): boolean {
  // 实现验证逻辑...
  return true;
}

// 使用示例
interface UserForm {
  name: FormField<string>;
  email: FormField<string>;
  age: FormField<number>;
}

const userForm: Validator<UserForm> = {
  name: {
    value: "John",
    rules: [{ type: "required" }, { type: "minLength", value: 2 }],
    touched: true,
  },
  email: {
    value: "john@example.com",
    rules: [
      { type: "required" },
      { type: "pattern", value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ }
    ],
    touched: false,
  },
  age: {
    value: 25,
    rules: [{ type: "required" }],
    touched: true,
  },
};

7.2 状态管理类型

// ===== 状态管理类型系统 =====

// Action 类型
interface Action<T = any, P = any> {
  type: T;
  payload?: P;
}

// Reducer 类型
type Reducer<S, A extends Action> = (state: S, action: A) => S;

// Middleware 类型
type Middleware<S, A extends Action> = (
  store: { getState(): S; dispatch(a: A): void }
) => (next: (a: A) => void) => (action: A) => void;

// 创建 Store 的类型
interface Store<S, A extends Action = Action> {
  getState(): S;
  dispatch(action: A): void;
  subscribe(listener: () => void): () => void;
}

// Thunk 类型
type Thunk<S, A extends Action> = (dispatch: (a: A) => void, getState: () => S) => void;
type AsyncAction<S, A extends Action> = Thunk<S, A> | A;

// 状态选择器
type Selector<S, R> = (state: S) => R;

// 创建带类型的选择器工厂
function createSelector<S, R>(selector: Selector<S, R>) {
  return selector;
}

7.3 路由系统类型

// ===== 路由系统类型 =====

// 路由定义
interface Route<
  Path extends string,
  Params extends string[] = [],
  Query extends string[] = [],
  Body = unknown
> {
  path: Path;
  params: Params;
  query: Query;
  body: Body;
}

// 解析路由参数
type ParseParams<Path extends string> = 
  Path extends `${string}:${infer Param}/${infer Rest}`
    ? [Param, ...ParseParams<`/${Rest}`>]
    : Path extends `${string}:${infer Param}`
    ? [Param]
    : [];

type Params1 = ParseParams<"/users/:id/posts/:postId">;
// ["id", "postId"]

type Params2 = ParseParams<"/users">;
// []

// 路径参数
type PathParams<Path extends string> = {
  [K in ParseParams<Path> as K]: string;
};

// 生成路径
type BuildPath<Path extends string, Params extends keyof any = never> = 
  Path extends `${string}:${infer Param}/${infer Rest}`
    ? Param extends Params
      ? `${string}/{${Param}}:${BuildPath<`/${Rest}`, Params>}`
      : never
    : Path extends `${string}:${infer Param}`
    ? Param extends Params
      ? `${string}/{${Param}}`
      : never
    : Path;

type BuiltPath = BuildPath<"/users/:id", "id">;
// "/users/{id}"

// 链接组件
interface LinkProps<Path extends string> {
  to: Path;
  params?: PathParams<Path>;
  query?: Record<string, string>;
  children: React.ReactNode;
}

八、性能与调试

8.1 类型性能

// ===== 类型计算性能 =====

// 避免深层嵌套
// ❌ 差:深度嵌套导致编译器变慢
type DeepNested<T> = { [K in keyof T]: DeepNested<T[K]> };

// ✅ 好:限制递归深度
type DeepNestedLimited<T, Depth extends number[]> = 
  Depth["length"] extends 0 ? T : 
  T extends object ? { [K in keyof T]: DeepNestedLimited<T[K], [-1, ...Depth]> } : T;

// 使用条件类型优化
type FastExtract<T, U> = T extends U ? T : never;  // 比 T extends any ? T : never 快

// 避免在映射类型中使用复杂计算
// ❌ 差
type SlowMap<T> = { [K in keyof T]: SomeComplexComputation<T[K]> };

// ✅ 好:先计算再映射
type Precomputed = SomeComplexComputation<T[keyof T]>;
type FastMap<T> = { [K in keyof T]: Precomputed };

8.2 类型调试技巧

// ===== 类型调试技巧 =====

// 使用 TODO 注释标记待处理类型
type TODO<T> = T;

// 使用 never 检测不可能的情况
type AssertNever<T> = T extends never ? true : false;

// 检查类型是否正确
type Check<T, Expected> = [T] extends [Expected] ? [Expected] extends [T] ? true : false : false;

// 打印类型(用于调试)
type Debug<T> = { [K in keyof T]: T[K] };
type Reveal<T> = T extends infer U ? U : never;

// 使用 const 断言辅助类型推断
const config = {
  api: {
    baseUrl: "https://api.example.com",
    timeout: 5000,
  } as const,
} as const;

type ConfigType = typeof config;
// { readonly api: { readonly baseUrl: "https://api.example.com"; readonly timeout: 5000 } }

// 使用 satisfies 验证
const colors = {
  red: "#ff0000",
  green: "#00ff00",
  blue: "#0000ff",
} satisfies Record<string, string>;

8.3 类型测试

// ===== 类型测试 =====

import { expectType } from "ts-expect";

// 类型级别测试
type Test<
  Actual extends string,
  Expected extends string
> = Actual extends Expected 
  ? Expected extends Actual 
    ? true 
    : false 
  : false;

// 示例测试
type Test1 = Test<ParseParams<"/users/:id">, ["id"]>;    // true
type Test2 = Test<ParseParams<"/users">, []>;              // true
type Test3 = Test<ParseParams<"/posts/:postId">, ["id"]>; // false

// 编译时断言
type Assert<T extends true> = T;

// 使用 Assert 确保条件成立
type AssertIsString<T> = T extends string ? Assert<true> : Assert<false>;

// 快速检查工具
type IsString<T> = T extends string ? "yes" : "no";
type IsArray<T> = T extends any[] ? "yes" : "no";
type IsObject<T> = T extends object ? "yes" : "no";

九、常见错误与解决

9.1 泛型约束错误

// ===== 常见泛型错误 =====

// 错误 1:约束不足
function first<T>(arr: T): T[0] {  // ❌ T 可能没有索引
  return arr[0];
}

// 解决:添加约束
function first<T extends any[]>(arr: T): T[0] {
  return arr[0];
}

// 错误 2:约束过严
function identity<T extends string>(value: T): T {  // ❌ 无法传入 number
  return value;
}

// 解决:使用更宽泛的约束
function identity<T>(value: T): T {
  return value;
}

// 错误 3:没有处理 never
type Extract<T, U> = T extends U ? T : never;

type Result = string | never;  // 永远是 string
// never 被自动移除

// 正确理解分布
type Test = "a" | "b" | "c" extends string ? true : false;  // true
// 联合类型作为整体比较

9.2 递归类型问题

// ===== 递归类型问题 =====

// 问题 1:类型太深导致循环
// ❌ 可能的无限递归
type DeepExpand<T> = T extends infer U ? { [K in keyof U]: DeepExpand<U[K]> } : T;
// 可能超出 TypeScript 限制

// 解决:添加深度限制
type DeepExpandLimited<T, Depth extends number = 5> = 
  Depth extends 0 
    ? T 
    : T extends object 
      ? { [K in keyof T]: DeepExpandLimited<T[K], [-1, ...Depth]> }
      : T;

// 问题 2:协变与逆变
interface Container<T> {
  value: T;
  setValue: (value: T) => void;  // 逆变
  getValue: () => T;              // 协变
}

// 问题 3:any 类型导致的意外结果
type Test1 = any extends string ? true : false;  // true(any 太宽泛)
type Test2 = string extends any ? true : false; // true

// 解决:使用 unknown 而非 any
type Test3 = unknown extends string ? true : false;  // false

9.3 映射类型问题

// ===== 映射类型问题 =====

// 问题 1:索引签名冲突
type A = { [key: string]: string };
type B = { [key: string]: number };
type AB = A & B;  // { [key: string]: string & number } = never

// 问题 2:可选属性处理
type Partial<T> = { [K in keyof T]?: T[K] };
// 可选属性可能包含 undefined

// 问题 3:只读属性处理
type Readonly<T> = { readonly [K in keyof T]: T[K] };
// 嵌套对象内部的属性可能仍然可变

// 解决:递归版本
type DeepPartial<T> = T extends object 
  ? { [K in keyof T]?: DeepPartial<T[K]> } 
  : T;

// 问题 4:键重映射中使用 never
type RemoveNull<T> = { [K in keyof T as T[K] extends null ? never : K]: T[K] };
// 正确使用 never 作为键

十、总结

10.1 知识体系总结

TypeScript
高级类型

条件类型

基础语法

分布式

infer

映射类型

基础映射

键重映射

修饰符

模板字面量

字符串操作

类型组合

路由系统

递归类型

深度递归

列表操作

路径访问

高级工具

Union处理

类型工厂

函数工具

10.2 学习路线图

入门

基础

进阶

精通

• 类型注解

• 泛型基础

• 基础工具类型

• 条件类型

• 映射类型

• 模板字面量

• 递归类型

• 类型工厂

• 高级工具类型

• 类型性能优化

• 类型测试

• 框架类型设计

10.3 推荐资源

类型 资源 说明
官方文档 TypeScript Handbook https://www.typescriptlang.org/docs/
书籍 《Programming TypeScript》 全面深入
网站 type-challenges 类型体操练习
网站 Total TypeScript 免费教程
工具 tsd 类型测试

附录:速查表

A. 常用工具类型

// 基础工具
Partial<T>
Required<T>
Readonly<T>
Pick<T, K>
Omit<T, K>
Record<K, V>
Exclude<T, U>
Extract<T, U>
NonNullable<T>
ReturnType<T>
Parameters<T>

// 高级工具
Mutable<T>
DeepPartial<T>
DeepReadonly<T>
RequiredKeys<T>
OptionalKeys<T>
IsNever<T>
IsAny<T>
IsEqual<A, B>

// 列表工具
Head<T>
Tail<T>
Last<T>
Prepend<T, V>
Append<T, V>
Reverse<T>

B. 类型操作符

// 条件类型
T extends U ? X : Y

// infer
T extends infer U ? U : never

// 键重映射
[K in keyof T as ...]: T[K]

// 模板字面量
`${string}${T}`

本文基于 TypeScript 4.5+ 编写。如有问题欢迎评论区讨论!

更多推荐