AgentSkillsCN

typescript-excellence

遵循TypeScript最佳实践,强化类型安全,落实工具链标准。适用于以下场景: - 编写或审查TypeScript代码 - 搭建TypeScript项目或配置tsconfig - 选择状态管理模式 - 配置构建工具(tsup、Vitest) - 避免过度复杂的类型推导或滥用any类型 关键词:TypeScript、tsconfig、严格模式、no-any、pnpm、Vitest、tsup、TanStack Query、区分联合类型、类型安全、ESLint

SKILL.md
--- frontmatter
name: typescript-excellence
description: |
  TypeScript best practices, type safety, and toolchain standards. Use when:
  - Writing or reviewing TypeScript code
  - Setting up TypeScript projects or tsconfig
  - Choosing state management patterns
  - Configuring build tools (tsup, Vitest)
  - Avoiding type gymnastics or any-abuse
  Keywords: TypeScript, tsconfig, strict mode, no-any, pnpm, Vitest, tsup,
  TanStack Query, discriminated unions, type safety, ESLint

TypeScript Excellence

Type-safe, maintainable TypeScript with modern toolchain.

Type Safety

Never use any. Alternatives:

typescript
// Unknown for external data
function parse(input: unknown): User { ... }

// Union for specific options
type Status = 'loading' | 'success' | 'error';

// Generics for reusable code
function first<T>(arr: T[]): T | undefined { ... }

// Type assertion as last resort (with runtime check)
if (isUser(data)) { return data as User; }

tsconfig.json essentials:

json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true
  }
}

Module Organization

Feature-based, not layer-based:

code
src/
  features/
    auth/
      components/
      hooks/
      api.ts
      types.ts
      index.ts  # Barrel: controlled exports
    orders/
      ...
  shared/
    ui/
    utils/

Use path aliases: @features/*, @shared/* (avoid ../../../../).

State Management

Server state: TanStack Query exclusively.

typescript
const { data, isLoading, error } = useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
});

Client state: Discriminated unions.

typescript
type AuthState =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'authenticated'; user: User }
  | { status: 'error'; error: AppError };

Async Patterns

Always wrap, always context:

typescript
async function fetchUser(id: string): Promise<User> {
  try {
    const res = await fetch(`/api/users/${id}`);
    if (!res.ok) throw new ApiError(res.status, await res.text());
    return res.json();
  } catch (error) {
    throw new AppError('Failed to fetch user', { cause: error });
  }
}

Cancellation: Use AbortController for long operations. Always clean up timeouts in finally blocks.

Toolchain

ToolPurpose
pnpmPackage manager (declare in packageManager field)
VitestTesting (unit/integration/e2e)
tsupBuilds (ESM + CJS + .d.ts)
ESLintLinting (@typescript-eslint/no-explicit-any: error)
PrettierFormatting

Anti-Patterns

  • Type gymnastics (conditional types, template literals without justification)
  • useState + useEffect for server data (use TanStack Query)
  • Technical-layer folders (/controllers, /services, /models)
  • eslint-disable without documented justification
  • Mocking internal components (mock boundaries only)
  • Mixed package managers or test frameworks

References