typescript-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TypeScript Expert

TypeScript 专家指南

Covers TypeScript through 5.8 (latest stable as of March 2026). The official handbook at https://www.typescriptlang.org/docs/handbook/ is the canonical reference.
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Its type system is structural (not nominal), meaning type compatibility is determined by shape rather than declaration. This has profound implications for how you design types and APIs.
涵盖至TypeScript 5.8版本(截至2026年3月的最新稳定版)。官方手册https://www.typescriptlang.org/docs/handbook/ 为权威参考资料。
TypeScript是JavaScript的类型化超集,可编译为普通JavaScript。它的类型系统采用结构类型(而非标称类型),即类型兼容性由形状而非声明决定。这对类型和API的设计有着深远影响。

Quick Decision Guide

快速决策指南

You need to...Read
Understand primitives, inference, narrowingcore-type-system
Choose between
interface
and
type
core-interfaces-types
Write generic functions, classes, constraintscore-generics
Use
Partial
,
Pick
,
Omit
,
Record
, etc.
core-utility-types
Build conditional types with
infer
advanced-conditional-types
Create mapped types and key remappingadvanced-mapped-types
Use template literal types for string patternsadvanced-template-literals
Narrow types with guards and discriminated unionsadvanced-type-guards
Use TC39 decorators (TS 5.0+)advanced-decorators
Configure
tsconfig.json
properly
best-practices-tsconfig
Apply common patterns (branded types, error handling, immutability)best-practices-patterns
Optimize type-level performancebest-practices-performance
Use TS 5.0-5.8 features (
satisfies
,
const
params,
using
)
features-ts5x
你需要...阅读文档
理解原始类型、类型推断、类型收窄core-type-system
选择
interface
还是
type
core-interfaces-types
编写泛型函数、类、约束core-generics
使用
Partial
Pick
Omit
Record
等工具类型
core-utility-types
结合
infer
构建条件类型
advanced-conditional-types
创建映射类型与键重映射advanced-mapped-types
使用模板字面量类型处理字符串模式advanced-template-literals
使用类型守卫与可辨识联合收窄类型advanced-type-guards
使用TC39标准装饰器(TS 5.0+)advanced-decorators
正确配置
tsconfig.json
best-practices-tsconfig
应用常见模式(品牌类型、错误处理、不可变性)best-practices-patterns
优化类型层面性能best-practices-performance
使用TS 5.0-5.8特性(
satisfies
const
参数、
using
features-ts5x

Core Principles

核心原则

1. Let TypeScript Infer

1. 尽量让TypeScript自动推断

TypeScript's inference is powerful. Don't annotate what TypeScript can figure out on its own:
typescript
// Unnecessary — TypeScript infers `number`
const count: number = 5;

// Good — let inference work
const count = 5;

// DO annotate function signatures (parameters + return types for public APIs)
function getUser(id: string): Promise<User> { ... }

// Return type annotation catches accidental returns
function parse(input: string): ParseResult {
  if (!input) return null; // Error! null isn't ParseResult — good, we caught a bug
}
TypeScript的推断能力很强。TypeScript能自动识别的类型,无需手动标注:
typescript
// 没必要——TypeScript会自动推断为`number`类型
const count: number = 5;

// 推荐——让推断自行工作
const count = 5;

// 公共API的函数签名必须标注(参数+返回类型)
function getUser(id: string): Promise<User> { ... }

// 返回类型标注可捕获意外返回值
function parse(input: string): ParseResult {
  if (!input) return null; // 错误!null不属于ParseResult类型——很好,我们提前发现了bug
}

2. Prefer
unknown
over
any

2. 优先使用
unknown
而非
any

any
disables type checking.
unknown
is type-safe — you must narrow it before use:
typescript
// Bad — silently breaks type safety
function process(data: any) {
  data.foo.bar; // No error, but might crash at runtime
}

// Good — forces you to check before using
function process(data: unknown) {
  if (typeof data === "object" && data !== null && "foo" in data) {
    // Now TypeScript knows data has a foo property
  }
}
any
会禁用类型检查。
unknown
是类型安全的——使用前必须先收窄类型:
typescript
// 不推荐——悄悄破坏类型安全
function process(data: any) {
  data.foo.bar; // 无编译错误,但运行时可能崩溃
}

// 推荐——强制你在使用前进行检查
function process(data: unknown) {
  if (typeof data === "object" && data !== null && "foo" in data) {
    // 此时TypeScript已知道data拥有foo属性
  }
}

3. Use Strict Mode

3. 启用严格模式

Always enable
"strict": true
in tsconfig.json. It enables all strict type-checking flags including
strictNullChecks
,
noImplicitAny
, and
strictFunctionTypes
. Projects that skip strict mode accumulate hidden bugs that surface painfully later. See best-practices-tsconfig for the full recommended configuration.
始终在tsconfig.json中启用
"strict": true
。它会开启所有严格类型检查标志,包括
strictNullChecks
noImplicitAny
strictFunctionTypes
。跳过严格模式的项目会积累隐藏bug,后续排查会非常痛苦。查看best-practices-tsconfig获取完整推荐配置。

4. Model Your Domain with Types

4. 用类型建模业务领域

The type system is a tool for encoding business rules. Use discriminated unions to model states, branded types for domain identifiers, and
readonly
to enforce immutability:
typescript
// Model states explicitly — impossible to access data in loading/error state
type AsyncState<T> =
  | { status: "loading" }
  | { status: "error"; error: Error }
  | { status: "success"; data: T };

// Branded types prevent ID mixups at compile time
type UserId = string & { readonly __brand: "UserId" };
type OrderId = string & { readonly __brand: "OrderId" };

function getOrder(orderId: OrderId): Order { ... }
getOrder(userId); // Error! UserId is not assignable to OrderId
类型系统是编码业务规则的工具。使用可辨识联合建模状态,品牌类型建模领域标识符,
readonly
强制不可变性:
typescript
// 显式建模状态——无法在加载/错误状态下访问数据
type AsyncState<T> =
  | { status: "loading" }
  | { status: "error"; error: Error }
  | { status: "success"; data: T };

// 品牌类型可在编译期防止ID混用
type UserId = string & { readonly __brand: "UserId" };
type OrderId = string & { readonly __brand: "OrderId" };

function getOrder(orderId: OrderId): Order { ... }
getOrder(userId); // 错误!UserId无法赋值给OrderId

5. Structural Typing Implications

5. 结构类型的影响

TypeScript uses structural typing — if two types have the same shape, they're compatible:
typescript
interface Point { x: number; y: number }
interface Coordinate { x: number; y: number }

const p: Point = { x: 1, y: 2 };
const c: Coordinate = p; // OK — same shape

// This means excess property checks only apply to object literals
function plot(point: Point) { ... }
plot({ x: 1, y: 2, z: 3 }); // Error — excess property check on literal
const obj = { x: 1, y: 2, z: 3 };
plot(obj); // OK — no excess check on variable
TypeScript采用结构类型——若两个类型形状相同,则它们兼容:
typescript
interface Point { x: number; y: number }
interface Coordinate { x: number; y: number }

const p: Point = { x: 1, y: 2 };
const c: Coordinate = p; // 允许——形状相同

// 这意味着多余属性检查仅适用于对象字面量
function plot(point: Point) { ... }
plot({ x: 1, y: 2, z: 3 }); // 错误——对字面量进行多余属性检查
const obj = { x: 1, y: 2, z: 3 };
plot(obj); // 允许——对变量不进行多余属性检查

Common Gotchas

常见陷阱

GotchaExplanation
object
vs
Object
vs
{}
Use
object
for non-primitives. Never use
Object
or
{}
as types —
{}
matches everything except
null
/
undefined
.
T[]
vs
readonly T[]
Arrays are mutable by default. Use
readonly T[]
or
ReadonlyArray<T>
when mutation isn't intended.
enum
vs union
Prefer union types (
type Dir = "N" | "S" | "E" | "W"
) over enums. Enums produce runtime code and have subtle nominal typing behavior. Use
as const
objects if you need runtime values.
Optional vs
undefined
{ x?: number }
means x may be missing entirely.
{ x: number | undefined }
means x must be present but can be undefined. These behave differently with
in
checks and spread.
as
casts
Type assertions (
as
) override the compiler. Prefer type guards for runtime narrowing. Use
as
only when you genuinely know more than TypeScript.
any
propagation
A single
any
silently infects surrounding types. Use
unknown
and narrow, or use
// @ts-expect-error
for known edge cases.
陷阱说明
object
vs
Object
vs
{}
object
表示非原始类型。绝不要用
Object
{}
作为类型——
{}
匹配除
null
/
undefined
外的所有值。
T[]
vs
readonly T[]
数组默认是可变的。当不需要修改时,使用
readonly T[]
ReadonlyArray<T>
enum
vs 联合类型
优先使用联合类型(
type Dir = "N" | "S" | "E" | "W"
)而非枚举。枚举会生成运行时代码,且存在细微的标称类型行为。若需要运行时值,使用
as const
对象。
可选属性 vs
undefined
{ x?: number }
表示x可能完全不存在。
{ x: number | undefined }
表示x必须存在,但可以是undefined。二者在
in
检查和展开操作中的表现不同。
as
类型断言
类型断言(
as
)会覆盖编译器检查。优先使用类型守卫进行运行时类型收窄。仅当你确实比TypeScript更了解类型时才使用
as
any
的传播
单个
any
会悄悄影响周围的类型。使用
unknown
并收窄类型,或在已知边缘情况使用
// @ts-expect-error

TypeScript 5.x Highlights

TypeScript 5.x 重要特性

Key features added in TypeScript 5.0-5.8 (see features-ts5x for details):
VersionFeatureWhy it matters
5.0TC39 DecoratorsStandard decorator syntax, no
experimentalDecorators
needed
5.0
const
type parameters
<const T>
gives const-like inference without
as const
at call site
5.1Easier implicit returns
undefined
-returning functions can omit
return
5.2
using
declarations
Deterministic resource cleanup (like C#
using
/ Python
with
)
5.4
NoInfer<T>
Prevents unwanted inference from specific positions
5.5Inferred type predicates
filter(Boolean)
and arrow guards just work
5.6Iterator helper methods
.map()
,
.filter()
,
.take()
on iterators
5.7
--squash
for project refs
Faster composite project builds
5.8
--erasableSyntaxOnly
Strip types without full compilation (Node.js
--strip-types
support)
TypeScript 5.0-5.8版本新增的关键特性(详情见features-ts5x):
版本特性重要性
5.0TC39标准装饰器标准装饰器语法,无需启用
experimentalDecorators
5.0
const
类型参数
<const T>
可在调用时实现类const的推断,无需额外
as const
5.1更宽松的隐式返回返回
undefined
的函数可省略
return
语句
5.2
using
声明
确定性资源清理(类似C#的
using
/ Python的
with
5.4
NoInfer<T>
防止特定位置出现不必要的类型推断
5.5推断类型谓词
filter(Boolean)
和箭头函数守卫可直接生效
5.6迭代器辅助方法迭代器支持
.map()
.filter()
.take()
等方法
5.7项目引用的
--squash
选项
复合项目构建速度更快
5.8
--erasableSyntaxOnly
选项
无需完整编译即可剥离类型(支持Node.js
--strip-types

When to Read the References

何时查阅参考文档

  • Writing a new module/library: Read core-generics and best-practices-patterns
  • Debugging a confusing type error: Read advanced-type-guards and core-type-system
  • Designing a type-safe API: Read advanced-conditional-types and advanced-mapped-types
  • Setting up a new project: Read best-practices-tsconfig
  • Migrating from JS or older TS: Read features-ts5x and best-practices-tsconfig
  • Performance issues with types: Read best-practices-performance
  • 编写新模块/库:阅读core-genericsbest-practices-patterns
  • 调试复杂类型错误:阅读advanced-type-guardscore-type-system
  • 设计类型安全的API:阅读advanced-conditional-typesadvanced-mapped-types
  • 搭建新项目:阅读best-practices-tsconfig
  • 从JS或旧版TS迁移:阅读features-ts5xbest-practices-tsconfig
  • 类型层面性能问题:阅读best-practices-performance