writing-typescript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTypeScript Development (2025)
TypeScript开发指南(2025版)
Core Principles
核心原则
- Strict typing: Enable all strict checks
- Parse, don't validate: Transform untrusted data at boundaries
- Composition over inheritance: Small, focused functions
- Explicit over implicit: No , prefer
anyunknown
- 严格类型检查:启用所有严格校验规则
- 解析而非校验:在边界处转换不可信数据
- 组合优于继承:使用小巧、单一职责的函数
- 显式优于隐式:禁用类型,优先使用
anyunknown
Toolchain
工具链
bash
bun # Runtime + package manager (fast)
vite # Frontend bundling
vitest # Testing
eslint # Linting
prettier # Formattingbash
bun # 运行时 + 包管理器(速度快)
vite # 前端打包工具
vitest # 测试工具
eslint # 代码检查工具
prettier # 代码格式化工具Quick Patterns
常用模式
Type Guards
Type Guards
typescript
function isUser(value: unknown): value is User {
return typeof value === "object" && value !== null && "id" in value;
}typescript
function isUser(value: unknown): value is User {
return typeof value === "object" && value !== null && "id" in value;
}Discriminated Unions
Discriminated Unions
typescript
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
function processResult<T>(result: Result<T>): T {
if (result.ok) return result.value;
throw result.error;
}typescript
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
function processResult<T>(result: Result<T>): T {
if (result.ok) return result.value;
throw result.error;
}Utility Types
Utility Types
typescript
type UserUpdate = Partial<User>;
type UserSummary = Pick<User, "id" | "name">;
type UserWithoutPassword = Omit<User, "password">;
type ReadonlyUser = Readonly<User>;typescript
type UserUpdate = Partial<User>;
type UserSummary = Pick<User, "id" | "name">;
type UserWithoutPassword = Omit<User, "password">;
type ReadonlyUser = Readonly<User>;tsconfig.json Essentials
tsconfig.json核心配置
json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"isolatedModules": true
}
}json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"isolatedModules": true
}
}References
参考资料
- PATTERNS.md - Code patterns and style
- REACT.md - React component patterns
- TESTING.md - Testing with vitest
- PATTERNS.md - 代码模式与风格规范
- REACT.md - React组件模式
- TESTING.md - 使用vitest进行测试
Commands
常用命令
bash
bun install # Install deps
bun run build # Build
bun test # Test
bun run lint # Lint
bun run format # Formatbash
bun install # 安装依赖
bun run build # 构建项目
bun test # 运行测试
bun run lint # 代码检查
bun run format # 代码格式化Gotchas
常见陷阱
- with
import typeand named exports: type-only import of a value triggers errors. Fix:verbatimModuleSyntax(inline marker).import { type Foo } from "mod" - on object: readonly AND literal-narrowed — different from
as const(asserts type) oras Foo(validates without widening).satisfies Foo - validates without widening;
satisfieswidens — usingaswhere you wantedasloses literal types silently.satisfies - requires
Array<T>.includes(x)to be of typex— narrowing-from-union doesn't work; the standard fix is a type-predicate helper.T - makes
strictNullChecks: falsemeanTfor ALL types — partial migrations leave types that lie about nullability.T | null | undefined tsconfig.jsondoesn't recursively mergeextends— child paths REPLACE parent paths, not merge.compilerOptions.paths
- 搭配使用
verbatimModuleSyntax和命名导出:对值进行仅类型导入会触发错误。修复方法:import type(内联标记)。import { type Foo } from "mod" - 在对象上使用:只读且字面量收窄 — 与
as const(断言类型)或as Foo(校验但不拓宽类型)不同。satisfies Foo - 校验但不拓宽类型;
satisfies会拓宽类型 — 在本该使用as的地方使用satisfies会悄无声息地丢失字面量类型。as - 要求
Array<T>.includes(x)为x类型 — 联合类型收窄不生效;标准修复方案是使用类型谓词助手。T - 会让所有
strictNullChecks: false类型等同于T— 部分迁移会留下无法准确反映空值情况的类型。T | null | undefined - 的
tsconfig.json不会递归合并extends— 子配置中的paths会替换父配置的paths,而非合并。compilerOptions.paths