← 返回文章列表

TypeScript 高级类型模式:写出更安全的代码

探索 TypeScript 的高级类型系统,包括条件类型、映射类型、模板字面量类型等,让你的代码在编译时就能捕获更多错误。

2025年3月5日·4 分钟阅读
字号

TypeScript 的类型系统远比大多数人想象的强大。本文深入探讨一些高级模式,帮你写出更健壮的代码。

条件类型(Conditional Types)

条件类型让类型具有了"判断能力":

type IsString<T> = T extends string ? true : false;
 
type A = IsString<string>;  // true
type B = IsString<number>;  // false

实用的内置条件类型

// 提取函数返回值类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
 
// 实际应用
async function fetchUser() {
  return { id: 1, name: 'Alice' };
}
 
type User = Awaited<ReturnType<typeof fetchUser>>;
// type User = { id: number; name: string }

映射类型(Mapped Types)

基于现有类型批量生成新类型:

// 将所有属性变为可选
type Partial<T> = { [K in keyof T]?: T[K] };
 
// 将所有属性变为只读
type Readonly<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];
};
 
interface User {
  id: number;
  name: string;
  age: number;
  email: string;
}
 
type StringFields = PickByValue<User, string>;
// { name: string; email: string }

模板字面量类型

4.1 引入的模板字面量类型极大增强了字符串类型能力:

type EventName = 'click' | 'focus' | 'blur';
type Handler = `on${Capitalize<EventName>}`;
// 'onClick' | 'onFocus' | 'onBlur'
 
// 实用场景:生成 CSS 变量类型
type CSSVariable<T extends string> = `--${T}`;
type ThemeVar = CSSVariable<'primary' | 'secondary' | 'background'>;
// '--primary' | '--secondary' | '--background'

辨别联合类型(Discriminated Unions)

构建类型安全的状态机:

type AsyncState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: string };
 
function renderState<T>(state: AsyncState<T>) {
  switch (state.status) {
    case 'idle':
      return '等待中...';
    case 'loading':
      return '加载中...';
    case 'success':
      return state.data; // TypeScript 知道这里有 data
    case 'error':
      return `错误:${state.error}`; // TypeScript 知道这里有 error
  }
}

函数重载类型

精确描述函数的多种调用方式:

function format(value: string): string;
function format(value: number, decimals: number): string;
function format(value: string | number, decimals?: number): string {
  if (typeof value === 'string') return value.trim();
  return value.toFixed(decimals ?? 2);
}
 
format('hello');    // ✅ 返回 string
format(3.14159, 2); // ✅ 返回 string
format(3.14);       // ❌ TypeScript 报错:number 重载需要 decimals 参数

实用工具类型大全

// 深层 Partial
type DeepPartial<T> = T extends object
  ? { [K in keyof T]?: DeepPartial<T[K]> }
  : T;
 
// 不可为空
type NonNullable<T> = T extends null | undefined ? never : T;
 
// 提取 Promise 的值类型
type Awaited<T> = T extends Promise<infer R> ? Awaited<R> : T;
 
// 获取数组元素类型
type ArrayElement<T extends readonly unknown[]> =
  T extends readonly (infer E)[] ? E : never;
 
const colors = ['red', 'green', 'blue'] as const;
type Color = ArrayElement<typeof colors>; // 'red' | 'green' | 'blue'

小结

TypeScript 的类型系统是图灵完备的,这些高级模式让你能够:

  • 在编译期捕获更多逻辑错误
  • 生成更精确的 API 类型
  • 减少运行时类型检查的需要
  • 让 IDE 提供更好的自动补全

关键是找到类型安全和代码可读性之间的平衡点。

分享

// RELATED_POSTS