typescript-pro

SKILL.md

TypeScript 专家

深度掌握 TypeScript 5.0+ 高级类型系统,构建零运行时类型错误的应用。

使用内置工具

  • read_file — 阅读现有 TypeScript 代码和类型定义
  • edit_file — 添加/修改类型注解、重构类型定义
  • run_commandnpx tsc --noEmit(类型检查)、npx tsc --showConfig(查看配置)
  • grep — 搜索 any 类型使用、缺少类型注解的位置

高级类型模式

泛型约束

// 约束泛型参数必须有 id 属性
function getById<T extends { id: string }>(items: T[], id: string): T | undefined {
  return items.find(item => item.id === id);
}

// 键约束:K 必须是 T 的键
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  const result = {} as Pick<T, K>;
  keys.forEach(key => { result[key] = obj[key]; });
  return result;
}

条件类型

// 根据输入类型推导返回类型
type ApiResponse<T> = T extends string
  ? { message: T }
  : T extends object
    ? { data: T }
    : { value: T };

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

// 提取函数返回类型中的非 undefined 部分
type NonNullableReturn<T extends (...args: any[]) => any> =
  NonNullable<ReturnType<T>>;

模板字面量类型

type EventName = `on${Capitalize<'click' | 'focus' | 'blur'>}`;
// → 'onClick' | 'onFocus' | 'onBlur'

type CSSProperty = `${string}-${string}`;
type HTTPMethod = `${'GET' | 'POST' | 'PUT' | 'DELETE'}`;

// API 路由类型安全
type ApiRoute = `/api/v1/${'users' | 'orders' | 'products'}`;

Branded Types(品牌类型)

// 防止不同 ID 类型混用
type UserId = string & { readonly __brand: 'UserId' };
type OrderId = string & { readonly __brand: 'OrderId' };

function createUserId(id: string): UserId {
  return id as UserId;
}

function getUser(id: UserId): User { /* ... */ }
function getOrder(id: OrderId): Order { /* ... */ }

const userId = createUserId('abc');
getUser(userId);    // ✅
// getOrder(userId); // ❌ 编译错误!类型不兼容

类型守卫

// 类型谓词
function isString(value: unknown): value is string {
  return typeof value === 'string';
}

// 断言函数
function assertDefined<T>(value: T | null | undefined, message?: string): asserts value is T {
  if (value == null) {
    throw new Error(message ?? 'Value is null or undefined');
  }
}

// 判别联合类型
type Result<T> =
  | { success: true; data: T }
  | { success: false; error: string };

function handleResult<T>(result: Result<T>) {
  if (result.success) {
    console.log(result.data);   // TypeScript 知道这里是 { data: T }
  } else {
    console.error(result.error); // TypeScript 知道这里是 { error: string }
  }
}

判别联合(状态机)

type RequestState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error };

function render<T>(state: RequestState<T>) {
  switch (state.status) {
    case 'idle':    return '等待开始';
    case 'loading': return '加载中...';
    case 'success': return `数据: ${JSON.stringify(state.data)}`;
    case 'error':   return `错误: ${state.error.message}`;
  }
}

Mapped Types(映射类型)

// 将所有属性变为可选且可为 null
type NullablePartial<T> = {
  [K in keyof T]?: T[K] | null;
};

// 从类型中提取所有方法
type Methods<T> = {
  [K in keyof T as T[K] extends (...args: any[]) => any ? K : never]: T[K];
};

// 为事件添加 on 前缀
type EventHandlers<T> = {
  [K in keyof T as `on${Capitalize<string & K>}`]: (value: T[K]) => void;
};

satisfies 操作符(TypeScript 4.9+)

// 验证类型但保留推断的字面量类型
const config = {
  port: 3000,
  host: 'localhost',
  debug: true,
} satisfies Record<string, string | number | boolean>;

// config.port 的类型是 3000(而非 number)
// config.host 的类型是 'localhost'(而非 string)

const 断言

// as const 使值成为字面量类型
const COLORS = {
  red: '#ff0000',
  green: '#00ff00',
  blue: '#0000ff',
} as const;

type Color = typeof COLORS[keyof typeof COLORS];
// → '#ff0000' | '#00ff00' | '#0000ff'

// 优于 enum 的模式
const Status = {
  Active: 'active',
  Inactive: 'inactive',
  Pending: 'pending',
} as const;

type Status = typeof Status[keyof typeof Status];

常用工具类型速查

工具类型 作用 示例
Partial<T> 所有属性可选 Partial<User>
Required<T> 所有属性必需 Required<Config>
Readonly<T> 所有属性只读 Readonly<State>
Pick<T, K> 选取部分属性 Pick<User, 'id' | 'name'>
Omit<T, K> 排除部分属性 Omit<User, 'password'>
Record<K, V> 键值映射 Record<string, number>
Exclude<T, U> 从联合中排除 Exclude<Status, 'deleted'>
Extract<T, U> 从联合中提取 Extract<Event, { type: 'click' }>
NonNullable<T> 排除 null/undefined NonNullable<string | null>
ReturnType<T> 函数返回类型 ReturnType<typeof fn>
Parameters<T> 函数参数类型 Parameters<typeof fn>
Awaited<T> 解包 Promise Awaited<Promise<string>>

tsconfig 最佳实践

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "exactOptionalPropertyTypes": true,
    "forceConsistentCasingInFileNames": true,
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "module": "ESNext",
    "target": "ES2022"
  }
}

编码原则

必须做

  • 启用 strict 模式及所有编译器标志
  • 使用类型优先的 API 设计
  • 为领域建模使用 Branded Types
  • 使用 satisfies 操作符验证类型
  • 使用判别联合实现状态机
  • 优化类型推导(减少显式注解)

绝不做

  • 无理由使用 any(用 unknown 替代)
  • 跳过公共 API 的类型定义
  • 混合 type-only 和值导入
  • 禁用 strict null checks
  • 无必要使用 as 类型断言
  • 使用 enum(优先用 as const 对象)

知识参考

TypeScript 5.0+、泛型、条件类型、映射类型、模板字面量类型、判别联合、类型守卫、Branded Types、tRPC、项目引用、增量编译、声明文件、const 断言、satisfies 操作符

Weekly Installs
1
GitHub Stars
15
First Seen
13 days ago
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1