typescript

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TypeScript Skill (2025-2026 Edition)

TypeScript 技能指南(2025-2026版)

This skill outlines the latest best practices for writing robust, performant, and type-safe TypeScript code, aligned with the 2025-2026 ecosystem (TypeScript 5.x and beyond).
本指南介绍了符合2025-2026生态(TypeScript 5.x及更高版本)的编写健壮、高性能、类型安全的TypeScript代码的最新最佳实践。

🚀 Key Trends & Features (2025/2026)

🚀 核心趋势与特性(2025/2026)

  • Native Speed: The transition to a Go-based compiler (native port) is underway (TS 7+), promising massive performance gains.
  • Default Strictness: Modern projects treat
    strict: true
    as the absolute baseline.
  • Framework First: TS is now deeply integrated into frameworks (Next.js, Remix, NestJS) rather than an add-on.
  • 原生性能: 基于Go实现的编译器(原生移植)正在推进中(TS 7+),有望带来大幅性能提升。
  • 默认严格模式: 现代项目将
    strict: true
    作为绝对基础配置。
  • 框架优先: TS现在已深度集成到各个框架(Next.js、Remix、NestJS)中,而非附加组件。

🛠️ Configuration Best Practices (
tsconfig.json
)

🛠️ 配置最佳实践(
tsconfig.json

Use strict defaults to prevent bugs before they happen.
json
{
  "compilerOptions": {
    /* Type Safety */
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "useUnknownInCatchVariables": true,
    "noUncheckedIndexedAccess": true, /* 2025 Essential: Prevents accessing undefined array indices */
    "exactOptionalPropertyTypes": true, /* Stricter optional property checks */

    /* Modules & Emit */
    "module": "NodeNext", /* or "ESNext" for pure frontend */
    "moduleResolution": "NodeNext", /* Aligns with modern Node.js ESM */
    "target": "ES2022", /* Modern runtimes support recent ES features */
    "skipLibCheck": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "verbatimModuleSyntax": true, /* Enforces strict import/export syntax (TS 5.0+) */
    
    /* Developer Experience */
    "allowSyntheticDefaultImports": true
  }
}
使用严格默认配置,提前规避Bug。
json
{
  "compilerOptions": {
    /* Type Safety */
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "useUnknownInCatchVariables": true,
    "noUncheckedIndexedAccess": true, /* 2025必备:防止访问未定义的数组索引 */
    "exactOptionalPropertyTypes": true, /* 更严格的可选属性检查 */

    /* Modules & Emit */
    "module": "NodeNext", /* 纯前端项目可使用"ESNext" */
    "moduleResolution": "NodeNext", /* 适配现代Node.js ESM规范 */
    "target": "ES2022", /* 现代运行时支持最新ES特性 */
    "skipLibCheck": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "verbatimModuleSyntax": true, /* 强制执行严格的导入/导出语法(TS 5.0+支持) */
    
    /* Developer Experience */
    "allowSyntheticDefaultImports": true
  }
}

🧩 Type Safety & Patterns

🧩 类型安全与常用模式

1.
unknown
over
any

1. 优先使用
unknown
而非
any

Never use
any
unless absolutely necessary (e.g., migrating legacy code). Use
unknown
and narrow the type safely.
typescript
// ❌ Bad
function processData(input: any) {
  input.doSomething(); // Runtime crash risk
}

// ✅ Good
function processData(input: unknown) {
  if (typeof input === 'string') {
    console.log(input.toUpperCase()); // Safe
  } else if (isCustomType(input)) {
    input.doSomething(); // Safe via type guard
  }
}
除非万不得已(比如迁移遗留代码),绝对不要使用
any
。请使用
unknown
并安全收窄类型。
typescript
// ❌ 错误示例
function processData(input: any) {
  input.doSomething(); // 存在运行时崩溃风险
}

// ✅ 正确示例
function processData(input: unknown) {
  if (typeof input === 'string') {
    console.log(input.toUpperCase()); // 类型安全
  } else if (isCustomType(input)) {
    input.doSomething(); // 通过类型守卫保证安全
  }
}

2.
satisfies
Operator (TS 4.9+)

2.
satisfies
运算符(TS 4.9+)

Use
satisfies
to validate a value matches a type without widening the type (preserving inference).
typescript
type Config = Record<string, string | number>;

const myConfig = {
  port: 8080,
  host: "localhost"
} satisfies Config;

// ✅ TS knows 'port' is a number directly, no casting needed.
myConfig.port.toFixed(2); 
使用
satisfies
验证值是否匹配类型,同时不会拓宽类型(保留原有类型推断)。
typescript
type Config = Record<string, string | number>;

const myConfig = {
  port: 8080,
  host: "localhost"
} satisfies Config;

// ✅ TS可以直接识别'port'是数字类型,无需强制转换
myConfig.port.toFixed(2); 

3. Immutable Data by Default

3. 默认使用不可变数据

Use
readonly
to prevent accidental mutations, especially for function arguments and React props.
typescript
interface User {
  readonly id: string;
  readonly name: string;
  tags: readonly string[]; // Immutable array
}

function printTags(tags: readonly string[]) {
  // tags.push("new"); // ❌ Error: Property 'push' does not exist on type 'readonly string[]'
}
使用
readonly
防止意外修改,尤其是函数参数和React props。
typescript
interface User {
  readonly id: string;
  readonly name: string;
  tags: readonly string[]; // 不可变数组
}

function printTags(tags: readonly string[]) {
  // tags.push("new"); // ❌ 报错:类型'readonly string[]'上不存在属性'push'
}

4. Template Literal Types

4. 模板字面量类型

Create precise string types for better autocompletion and safety.
typescript
type EventName = "click" | "hover";
type HandlerName = `on${Capitalize<EventName>}`; // "onClick" | "onHover"
创建精确的字符串类型,实现更好的自动补全和类型安全。
typescript
type EventName = "click" | "hover";
type HandlerName = `on${Capitalize<EventName>}`; // 结果为"onClick" | "onHover"

⚡ Performance Optimization

⚡ 性能优化

  • Type Imports: Use
    import type { ... }
    or
    import { type ... }
    explicitly. Enabling
    verbatimModuleSyntax
    enforces this, ensuring zero JS overhead for type-only imports using modern bundlers.
  • Lazy Loading: Leverage
    await import(...)
    for splitting code in large applications.
  • 类型导入: 显式使用
    import type { ... }
    或者
    import { type ... }
    。开启
    verbatimModuleSyntax
    可强制执行该规则,确保现代打包器处理仅类型导入时不会产生任何JS运行时开销。
  • 懒加载: 在大型应用中使用
    await import(...)
    拆分代码。

⚠️ Common Pitfalls to Avoid

⚠️ 需要避免的常见陷阱

  • Excessive Type Assertions (
    as
    ):
    Use type guards or
    zod
    for validation instead of forcing types with
    as
    .
  • Broad Types: Avoid
    Function
    or
    object
    . Use
    () => void
    or
    Record<string, unknown>
    instead.
  • Enum Misuse: Prefer union types of strings (
    type Status = 'open' | 'closed'
    ) over standard TS
    enum
    s to keep runtime code cleaner and avoid nominal typing surprises.
  • 滥用类型断言(
    as
    ):
    请使用类型守卫或者
    zod
    做验证,而非用
    as
    强制指定类型。
  • 过宽的类型: 避免使用
    Function
    或者
    object
    ,请改用
    () => void
    或者
    Record<string, unknown>
  • 误用Enum: 优先使用字符串联合类型
    type Status = 'open' | 'closed'
    )而非标准TS
    enum
    ,可以让运行时代码更简洁,避免名义类型的意外问题。

📚 References

📚 参考资料