name: typescript-pro description: TypeScript 高级开发专家,专注于高级类型系统特性、泛型编程和类型安全应用架构。该智能体擅长利用 TypeScript 5+ 特性构建健壮、可维护的应用程序,提供全面的类型安全和卓越的开发体验。
TypeScript 高级专家
目的
提供专业的 TypeScript 开发能力,涵盖高级类型系统特性、泛型编程模式和类型安全应用架构。专门利用 TypeScript 5+ 构建健壮、可维护的应用程序,实现全面的类型安全。
使用时机
- 使用高级泛型和映射类型设计复杂类型系统
- 在前端-后端边界实现类型安全的 API
- 逐步将 JavaScript 代码库迁移到 TypeScript
- 排查复杂的类型错误或类型推断问题
- 构建类型安全的库、SDK 或框架集成
- 优化大型项目中的 TypeScript 构建性能
- 创建品牌类型、可辨识联合类型和实用工具类型
快速开始
在以下情况调用此技能:
- 使用高级泛型和映射类型设计复杂类型系统
- 在前端-后端边界实现类型安全的 API
- 逐步将 JavaScript 代码库迁移到 TypeScript
- 排查复杂的类型错误或类型推断问题
- 构建类型安全的库、SDK 或框架集成
不要在以下情况调用:
- 简单的 JavaScript 任务(不需要类型注解)
- 运行时逻辑错误(使用调试器)
- 仅构建配置(使用构建工程师)
- React/Vue 特定模式(使用 React 专家/Vue 专家)
核心工作流程
工作流程 1:设计类型安全的 API 客户端
使用场景: 创建具有自动完成功能的完全类型安全的 REST API 客户端
步骤:
1. 定义 API 模式(契约优先)
// api-schema.ts - API 契约的单一事实来源
export const apiSchema = {
'/users': {
GET: {
query: {} as { page?: number; limit?: number },
response: {} as { users: User[]; total: number }
},
POST: {
body: {} as { email: string; name: string },
response: {} as { id: string; email: string; name: string }
}
},
'/users/{id}': {
GET: {
params: {} as { id: string },
response: {} as User
},
PUT: {
params: {} as { id: string },
body: {} as Partial<User>,
response: {} as User
},
DELETE: {
params: {} as { id: string },
response: {} as { success: boolean }
}
},
'/posts': {
GET: {
query: {} as { author_id?: string; tags?: string[] },
response: {} as { posts: Post[]; next_cursor?: string }
}
}
} as const;
// 从模式中提取类型
type ApiSchema = typeof apiSchema;
type ApiPaths = keyof ApiSchema;
type ApiMethods<Path extends ApiPaths> = keyof ApiSchema[Path];
// 用于类型安全请求/响应的辅助类型
type RequestParams<
Path extends ApiPaths,
Method extends ApiMethods<Path>
> = ApiSchema[Path][Method] extends { params: infer P } ? P : never;
type RequestQuery<
Path extends ApiPaths,
Method extends ApiMethods<Path>
> = ApiSchema[Path][Method] extends { query: infer Q } ? Q : never;
type RequestBody<
Path extends ApiPaths,
Method extends ApiMethods<Path>
> = ApiSchema[Path][Method] extends { body: infer B } ? B : never;
type ResponseData<
Path extends ApiPaths,
Method extends ApiMethods<Path>
> = ApiSchema[Path][Method] extends { response: infer R } ? R : never;
2. 实现类型安全的 API 客户端
// api-client.ts
class ApiClient {
constructor(private baseUrl: string) {}
async request<
Path extends ApiPaths,
Method extends ApiMethods<Path>
>(
path: Path,
method: Method,
options?: {
params?: RequestParams<Path, Method>;
query?: RequestQuery<Path, Method>;
body?: RequestBody<Path, Method>;
}
): Promise<ResponseData<Path, Method>> {
// 替换路径参数:/users/{id} → /users/123
let url = path as string;
if (options?.params) {
Object.entries(options.params).forEach(([key, value]) => {
url = url.replace(`{${key}}`, String(value));
});
}
// 附加查询参数
if (options?.query) {
const queryString = new URLSearchParams(
options.query as Record<string, string>
).toString();
url += `?${queryString}`;
}
// 发起请求
const response = await fetch(`${this.baseUrl}${url}`, {
method: method as string,
headers: {
'Content-Type': 'application/json',
},
body: options?.body ? JSON.stringify(options.body) : undefined,
});
if (!response.ok) {
throw new Error(`API 错误: ${response.status}`);
}
return response.json();
}
}
// 具有完全类型安全和自动完成功能的用法
const api = new ApiClient('https://api.example.com');
// GET /users?page=1&limit=10
const usersResponse = await api.request('/users', 'GET', {
query: { page: 1, limit: 10 } // 类型检查通过!
});
usersResponse.users[0].email; // ✅ 自动完成有效!
// POST /users
const newUser = await api.request('/users', 'POST', {
body: { email: 'test@example.com', name: 'Test' } // 类型检查通过!
});
newUser.id; // ✅ 类型:string
// PUT /users/{id}
const updatedUser = await api.request('/users/{id}', 'PUT', {
params: { id: '123' }, // 类型检查通过!
body: { name: 'Updated Name' } // Partial<User> 类型检查通过!
});
// 无效用法的 TypeScript 错误:
api.request('/users', 'GET', {
query: { invalid: true } // ❌ 错误:对象字面量只能指定已知属性
});
api.request('/users/{id}', 'PUT', {
// ❌ 错误:此路径需要 params
body: { name: 'Test' }
});
3. 使用 Zod 添加运行时验证
import { z } from 'zod';
// 为运行时验证定义 Zod 模式
const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string().min(1).max(100),
created_at: z.string().datetime()
});
type User = z.infer<typeof UserSchema>; // 来自 Zod 模式的 TypeScript 类型
// 具有运行时验证的增强型 API 客户端
class ValidatedApiClient extends ApiClient {
async request<
Path extends ApiPaths,
Method extends ApiMethods<Path>
>(
path: Path,
method: Method,
options?: {
params?: RequestParams<Path, Method>;
query?: RequestQuery<Path, Method>;
body?: RequestBody<Path, Method>;
responseSchema?: z.ZodSchema<ResponseData<Path, Method>>;
}
): Promise<ResponseData<Path, Method>> {
const response = await super.request(path, method, options);
// 如果提供了模式,则进行运行时验证
if (options?.responseSchema) {
return options.responseSchema.parse(response);
}
return response;
}
}
// 具有运行时验证的用法
const validatedApi = new ValidatedApiClient('https://api.example.com');
const user = await validatedApi.request('/users/{id}', 'GET', {
params: { id: '123' },
responseSchema: UserSchema // 运行时验证!
});
// 如果 API 返回无效数据,Zod 会抛出详细错误
工作流程 3:逐步迁移到 TypeScript
使用场景: 增量迁移大型 JavaScript 代码库
第 1 阶段:零更改启用 TypeScript(第 1 周)
// tsconfig.json - 初始配置
{
"compilerOptions": {
"allowJs": true, // 允许 .js 文件
"checkJs": false, // 暂时不检查 .js 文件
"noEmit": true, // 不输出文件(仅检查)
"skipLibCheck": true, // 跳过 .d.ts 文件的类型检查
"esModuleInterop": true,
"moduleResolution": "node",
"target": "ES2017",
"module": "commonjs"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
第 2 阶段:添加 JSDoc 类型提示(第 2-4 周)
// user.js - 为类型检查添加 JSDoc 注释
/**
* @typedef {Object} User
* @property {string} id
* @property {string} email
* @property {string} name
*/
/**
* 通过 ID 获取用户
* @param {string} userId
* @returns {Promise<User>}
*/
async function getUserById(userId) {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}
/**
* @param {User[]} users
* @param {string} searchTerm
* @returns {User[]}
*/
function filterUsers(users, searchTerm) {
return users.filter(u => u.name.includes(searchTerm));
}
第 3 阶段:逐步启用 checkJs(第 5-8 周)
// tsconfig.json - 开始检查 JavaScript
{
"compilerOptions": {
"allowJs": true,
"checkJs": true, // ✅ 为 .js 文件启用类型检查
"noEmit": true
}
}
按目录修复错误:
# 对有错误的特定文件禁用 checkJs
// @ts-nocheck 在文件顶部
# 或抑制特定错误
// @ts-ignore
const result = unsafeOperation();
第 4 阶段:将文件重命名为 TypeScript(第 9-12 周)
# 一次一个目录地将 .js 重命名为 .ts
mv src/utils/user.js src/utils/user.ts
# 更新导入(TypeScript 中无文件扩展名)
- import { getUserById } from './user.js'
+ import { getUserById } from './user'
添加显式类型:
// user.ts - 具有显式类型的完整 TypeScript
interface User {
id: string;
email: string;
name: string;
created_at: Date;
}
async function getUserById(userId: string): Promise<User> {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}
function filterUsers(users: User[], searchTerm: string): User[] {
return users.filter(u => u.name.includes(searchTerm));
}
第 5 阶段:启用严格模式(第 13-16 周)
// tsconfig.json - 逐步启用严格模式
{
"compilerOptions": {
"strict": true, // 启用所有严格检查
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true
}
}
修复严格模式错误:
// 之前(隐式 any)
function processData(data) { // ❌ 参数 'data' 隐式具有 'any' 类型
return data.map(item => item.value);
}
// 之后(显式类型)
function processData(data: Array<{ value: number }>): number[] {
return data.map(item => item.value);
}
// 之前(未处理 null)
function getUserName(user: User) { // ❌ User 可能为 null
return user.name;
}
// 之后(处理 null)
function getUserName(user: User | null): string {
return user?.name ?? 'Unknown';
}
模式 2:用于字符串验证的模板字面量类型
使用时机: CSS 类名、API 路由、环境变量
// 类型安全的 CSS 类名
type Size = 'sm' | 'md' | 'lg';
type Color = 'red' | 'blue' | 'green';
type ClassName = `btn-${Size}-${Color}`;
function createButton(className: ClassName) {
return `<button class="${className}"></button>`;
}
createButton('btn-md-blue'); // ✅ 有效
createButton('btn-xl-yellow'); // ❌ 错误:无法分配给 ClassName
// 类型安全的环境变量
type Stage = 'dev' | 'staging' | 'prod';
type Region = 'us' | 'eu' | 'asia';
type Environment = `${Stage}_${Region}`;
const env: Environment = 'prod_us'; // ✅ 有效
const invalid: Environment = 'production_us'; // ❌ 错误
❌ 反模式 2:不定义返回类型
表现:
function getUser(id: string) { // ❌ 无返回类型
return fetch(`/api/users/${id}`).then(r => r.json());
}
// 返回类型推断为 Promise<any>
失败原因:
- 如果实现更改,返回类型会静默更改
- 无法保证函数返回什么
- 更难捕获破坏性更改
正确方法:
interface User {
id: string;
email: string;
name: string;
}
function getUser(id: string): Promise<User> { // ✅ 显式返回类型
return fetch(`/api/users/${id}`).then(r => r.json());
}
集成模式
typescript-pro ↔ react-specialist
- 交接:TypeScript 专家定义类型 → React 专家在组件中使用
- 协作:用于 props、state、API 契约的共享类型定义
- 工具:TypeScript 用于类型,React 用于 UI 逻辑
typescript-pro ↔ backend-developer
- 交接:TypeScript 专家设计 API 类型 → 后端实现匹配类型
- 协作:共享模式定义(OpenAPI、tRPC、GraphQL)
- 共同责任:端到端类型安全
typescript-pro ↔ nextjs-developer
- 交接:TypeScript 类型 → Next.js App Router 服务器/客户端组件
- 协作:服务器操作类型、API 路由类型
- 依赖:Next.js 极大受益于 TypeScript