mcpField
T
typescript-pro

typescript-pro

github.com/404kidwiz开发109 次安装
代码仓库

关于 typescript-pro

typescript-pro 面向 TypeScript 开发者,涵盖复杂类型设计、类型安全 API 和 JavaScript 迁移。它提供类型问题排查及大型项目构建性能方面的工作流指导。

主要功能

  1. 01高级泛型与映射类型
  2. 02类型安全 API 设计
  3. 03渐进式 JavaScript 迁移
  4. 04类型错误与推断问题排查
  5. 05TypeScript 构建性能指导

适用场景

  1. 01设计可复用的类型系统
  2. 02在应用层之间共享 API 类型
  3. 03迁移大型 JavaScript 代码库
  4. 04诊断复杂编译器错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/404kidwiz/claude-supercode-skills --skill typescript-pro

安装后在 Claude Code 中输入/typescript-pro确认已加载。

详细介绍

TypeScript 专家

用途

提供专业的 TypeScript 开发能力,涵盖高级类型系统特性、泛型编程模式和类型安全的应用架构。专注于运用 TypeScript 5+ 构建健壮、易于维护且具备全面类型安全性的应用。

适用场景

  • 使用高级泛型和映射类型设计复杂的类型系统
  • 在前后端边界实现类型安全的 API
  • 逐步将 JavaScript 代码库迁移到 TypeScript
  • 排查复杂的类型错误或类型推断问题
  • 构建类型安全的库、SDK 或框架集成
  • 优化大型项目中的 TypeScript 构建性能
  • 创建品牌类型、可辨识联合类型和工具类型

快速开始

适用于以下场景:

  • 使用高级泛型和映射类型设计复杂的类型系统
  • 在前后端边界实现类型安全的 API
  • 逐步将 JavaScript 代码库迁移到 TypeScript
  • 排查复杂的类型错误或类型推断问题
  • 构建类型安全的库、SDK 或框架集成

以下场景请勿使用:

  • 简单的 JavaScript 任务(无需类型注解)
  • 运行时逻辑错误(改用调试器)
  • 仅涉及构建配置(改用 build-engineer)
  • React/Vue 专属模式(改用 react-specialist/vue-expert)


核心工作流

工作流 1:设计类型安全的 API 客户端

适用场景: 创建具备自动补全功能的完全类型安全 REST API 客户端

步骤:

1. 定义 API 架构(契约优先)

// api-schema.ts - Single source of truth for API contract
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;

// Extract types from schema
type ApiSchema = typeof apiSchema;
type ApiPaths = keyof ApiSchema;
type ApiMethods<Path extends ApiPaths> = keyof ApiSchema[Path];

// Helper types for type-safe request/response
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>> {
    // Replace path parameters: /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));
      });
    }

    // Append query parameters
    if (options?.query) {
      const queryString = new URLSearchParams(
        options.query as Record<string, string>
      ).toString();
      url += `?${queryString}`;
    }

    // Make request
    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 Error: ${response.status}`);
    }

    return response.json();
  }
}

// Usage with full type safety and auto-completion
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 }  // Type-checked!
});
usersResponse.users[0].email;  // ✅ Auto-complete works!

// POST /users
const newUser = await api.request('/users', 'POST', {
  body: { email: '[email protected]', name: 'Test' }  // Type-checked!
});
newUser.id;  // ✅ Type: string

// PUT /users/{id}
const updatedUser = await api.request('/users/{id}', 'PUT', {
  params: { id: '123' },  // Type-checked!
  body: { name: 'Updated Name' }  // Partial<User> type-checked!
});

// TypeScript errors for invalid usage:
api.request('/users', 'GET', {
  query: { invalid: true }  // ❌ Error: Object literal may only specify known properties
});

api.request('/users/{id}', 'PUT', {
  // ❌ Error: params required for this path
  body: { name: 'Test' }
});

3. 使用 Zod 添加运行时验证

import { z } from 'zod';

// Define Zod schemas for runtime validation
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>;  // TypeScript type from Zod schema

// Enhanced API client with runtime validation
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);

    // Runtime validation if schema provided
    if (options?.responseSchema) {
      return options.responseSchema.parse(response);
    }

    return response;
  }
}

// Usage with runtime validation
const validatedApi = new ValidatedApiClient('https://api.example.com');

const user = await validatedApi.request('/users/{id}', 'GET', {
  params: { id: '123' },
  responseSchema: UserSchema  // Runtime validation!
});
// If API returns invalid data, Zod throws detailed error


工作流 3:逐步迁移到 TypeScript

适用场景: 逐步迁移大型 JavaScript 代码库

阶段 1:启用 TypeScript,不做任何改动(第 1 周)

// tsconfig.json - Initial configuration
{
  "compilerOptions": {
    "allowJs": true,          // Allow .js files
    "checkJs": false,         // Don't check .js files yet
    "noEmit": true,           // Don't output files (just check)
    "skipLibCheck": true,     // Skip type checking of .d.ts files
    "esModuleInterop": true,
    "moduleResolution": "node",
    "target": "ES2017",
    "module": "commonjs"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

阶段 2:添加 JSDoc 类型提示(第 2–4 周)

// user.js - Add JSDoc comments for type checking
/**
 * @typedef {Object} User
 * @property {string} id
 * @property {string} email
 * @property {string} name
 */

/**
 * Fetch user by 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 - Start checking JavaScript
{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,  // ✅ Enable type checking for .js files
    "noEmit": true
  }
}

按目录逐一修复错误:

# Disable checkJs for specific files with errors
// @ts-nocheck at top of file

# Or suppress specific errors
// @ts-ignore
const result = unsafeOperation();

阶段 4:将文件重命名为 TypeScript 文件(第 9–12 周)

# Rename .js → .ts one directory at a time
mv src/utils/user.js src/utils/user.ts

# Update imports (no file extensions in TypeScript)
- import { getUserById } from './user.js'
+ import { getUserById } from './user'

添加显式类型:

// user.ts - Full TypeScript with explicit types
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 - Enable strict mode progressively
{
  "compilerOptions": {
    "strict": true,  // Enable all strict checks
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true
  }
}

修复严格模式错误:

// Before (implicit any)
function processData(data) {  // ❌ Parameter 'data' implicitly has 'any' type
  return data.map(item => item.value);
}

// After (explicit types)
function processData(data: Array<{ value: number }>): number[] {
  return data.map(item => item.value);
}

// Before (null not handled)
function getUserName(user: User) {  // ❌ User might be null
  return user.name;
}

// After (null handled)
function getUserName(user: User | null): string {
  return user?.name ?? 'Unknown';
}


模式 2:使用模板字面量类型验证字符串

适用场景: CSS 类名、API 路由、环境变量

// Type-safe CSS class names
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');  // ✅ Valid
createButton('btn-xl-yellow');  // ❌ Error: Not assignable to ClassName

// Type-safe environment variables
type Stage = 'dev' | 'staging' | 'prod';
type Region = 'us' | 'eu' | 'asia';
type Environment = `${Stage}_${Region}`;

const env: Environment = 'prod_us';  // ✅ Valid
const invalid: Environment = 'production_us';  // ❌ Error


❌ 反模式 2:不定义返回类型

表现形式:

function getUser(id: string) {  // ❌ No return type
  return fetch(`/api/users/${id}`).then(r => r.json());
}
// Return type inferred as Promise<any>

问题所在:

  • 实现发生变化时,返回类型会悄然改变
  • 无法保证函数的返回内容
  • 更难发现破坏性变更

正确做法:

interface User {
  id: string;
  email: string;
  name: string;
}

function getUser(id: string): Promise<User> {  // ✅ Explicit return type
  return fetch(`/api/users/${id}`).then(r => r.json());
}


集成模式

typescript-pro ↔ react-specialist
  • 交接: TypeScript 专家定义类型 → React 专家在组件中使用这些类型
  • 协作: 共享 props、状态和 API 契约的类型定义
  • 工具: 使用 TypeScript 定义类型,使用 React 实现 UI 逻辑
typescript-pro ↔ backend-developer
  • 交接: TypeScript 专家设计 API 类型 → 后端开发者实现匹配的类型
  • 协作: 共享架构定义(OpenAPI、tRPC、GraphQL)
  • 共同职责: 端到端类型安全
typescript-pro ↔ nextjs-developer
  • 交接: TypeScript 类型 → Next.js App Router 服务端/客户端组件
  • 协作: Server Actions 类型、API 路由类型
  • 依赖关系: Next.js 可从 TypeScript 中受益匪浅

评论

支持 Markdown