mastering-typescript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMastering Modern TypeScript
精通现代TypeScript
Build enterprise-grade, type-safe applications with TypeScript 5.9+.
Compatibility: TypeScript 5.9+, Node.js 22 LTS, Vite 7, NestJS 11, React 19
使用TypeScript 5.9+构建企业级、类型安全的应用。
兼容性: TypeScript 5.9+、Node.js 22 LTS、Vite 7、NestJS 11、React 19
Quick Start
快速开始
bash
undefinedbash
undefinedInitialize TypeScript project with ESM
Initialize TypeScript project with ESM
pnpm create vite@latest my-app --template vanilla-ts
cd my-app && pnpm install
pnpm create vite@latest my-app --template vanilla-ts
cd my-app && pnpm install
Configure strict TypeScript
Configure strict TypeScript
cat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"target": "ES2024",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
EOF
undefinedcat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"target": "ES2024",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
EOF
undefinedWhen to Use This Skill
适用场景
Use when:
- Building type-safe React, NestJS, or Node.js applications
- Migrating JavaScript codebases to TypeScript
- Implementing advanced type patterns (generics, mapped types, conditional types)
- Configuring modern TypeScript toolchains (Vite, pnpm, ESLint)
- Designing type-safe API contracts with Zod validation
- Comparing TypeScript approaches with Java or Python
适用于以下场景:
- 构建类型安全的React、NestJS或Node.js应用
- 将JavaScript代码库迁移至TypeScript
- 实现高级类型模式(泛型、映射类型、条件类型)
- 配置现代化TypeScript工具链(Vite、pnpm、ESLint)
- 使用Zod验证设计类型安全的API契约
- 对比TypeScript与Java或Python的开发方式
Project Setup Checklist
项目设置检查清单
Before starting any TypeScript project:
- [ ] Use pnpm for package management (faster, disk-efficient)
- [ ] Configure ESM-first (type: "module" in package.json)
- [ ] Enable strict mode in tsconfig.json
- [ ] Set up ESLint with @typescript-eslint
- [ ] Add Prettier for consistent formatting
- [ ] Configure Vitest for testing启动任何TypeScript项目前:
- [ ] 使用pnpm进行包管理(更快、磁盘占用更低)
- [ ] 配置ESM优先(在package.json中设置type: "module")
- [ ] 在tsconfig.json中启用严格模式
- [ ] 配置ESLint与@typescript-eslint
- [ ] 添加Prettier以保证格式一致
- [ ] 配置Vitest用于测试Type System Quick Reference
类型系统快速参考
Primitive Types
原始类型
typescript
const name: string = "Alice";
const age: number = 30;
const active: boolean = true;
const id: bigint = 9007199254740991n;
const key: symbol = Symbol("unique");typescript
const name: string = "Alice";
const age: number = 30;
const active: boolean = true;
const id: bigint = 9007199254740991n;
const key: symbol = Symbol("unique");Union and Intersection Types
联合类型与交叉类型
typescript
// Union: value can be one of several types
type Status = "pending" | "approved" | "rejected";
// Intersection: value must satisfy all types
type Employee = Person & { employeeId: string };
// Discriminated union for type-safe handling
type Result<T> =
| { success: true; data: T }
| { success: false; error: string };
function handleResult<T>(result: Result<T>): T | null {
if (result.success) {
return result.data; // TypeScript knows data exists here
}
console.error(result.error);
return null;
}typescript
// Union: value can be one of several types
type Status = "pending" | "approved" | "rejected";
// Intersection: value must satisfy all types
type Employee = Person & { employeeId: string };
// Discriminated union for type-safe handling
type Result<T> =
| { success: true; data: T }
| { success: false; error: string };
function handleResult<T>(result: Result<T>): T | null {
if (result.success) {
return result.data; // TypeScript knows data exists here
}
console.error(result.error);
return null;
}Type Guards
类型守卫
typescript
// typeof guard
function process(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
// Custom type guard
interface User { type: "user"; name: string }
interface Admin { type: "admin"; permissions: string[] }
function isAdmin(person: User | Admin): person is Admin {
return person.type === "admin";
}typescript
// typeof guard
function process(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
// Custom type guard
interface User { type: "user"; name: string }
interface Admin { type: "admin"; permissions: string[] }
function isAdmin(person: User | Admin): person is Admin {
return person.type === "admin";
}The satisfies
Operator (TS 5.0+)
satisfiessatisfies
操作符(TS 5.0+)
satisfiesValidate type conformance while preserving inference:
typescript
// Problem: Type assertion loses specific type info
const colors1 = {
red: "#ff0000",
green: "#00ff00"
} as Record<string, string>;
colors1.red.toUpperCase(); // OK, but red could be undefined
// Solution: satisfies preserves literal types
const colors2 = {
red: "#ff0000",
green: "#00ff00"
} satisfies Record<string, string>;
colors2.red.toUpperCase(); // OK, and TypeScript knows red exists在保留类型推断的同时验证类型一致性:
typescript
// Problem: Type assertion loses specific type info
const colors1 = {
red: "#ff0000",
green: "#00ff00"
} as Record<string, string>;
colors1.red.toUpperCase(); // OK, but red could be undefined
// Solution: satisfies preserves literal types
const colors2 = {
red: "#ff0000",
green: "#00ff00"
} satisfies Record<string, string>;
colors2.red.toUpperCase(); // OK, and TypeScript knows red existsGenerics Patterns
泛型模式
Basic Generic Function
基础泛型函数
typescript
function first<T>(items: T[]): T | undefined {
return items[0];
}
const num = first([1, 2, 3]); // number | undefined
const str = first(["a", "b"]); // string | undefinedtypescript
function first<T>(items: T[]): T | undefined {
return items[0];
}
const num = first([1, 2, 3]); // number | undefined
const str = first(["a", "b"]); // string | undefinedConstrained Generics
约束泛型
typescript
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): T {
console.log(item.length);
return item;
}
logLength("hello"); // OK: string has length
logLength([1, 2, 3]); // OK: array has length
logLength(42); // Error: number has no lengthtypescript
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): T {
console.log(item.length);
return item;
}
logLength("hello"); // OK: string has length
logLength([1, 2, 3]); // OK: array has length
logLength(42); // Error: number has no lengthGeneric API Response Wrapper
泛型API响应包装器
typescript
interface ApiResponse<T> {
data: T;
status: number;
timestamp: Date;
}
async function fetchUser(id: string): Promise<ApiResponse<User>> {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
return {
data,
status: response.status,
timestamp: new Date()
};
}typescript
interface ApiResponse<T> {
data: T;
status: number;
timestamp: Date;
}
async function fetchUser(id: string): Promise<ApiResponse<User>> {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
return {
data,
status: response.status,
timestamp: new Date()
};
}Utility Types Reference
工具类型参考
| Type | Purpose | Example |
|---|---|---|
| All properties optional | |
| All properties required | |
| Select specific properties | |
| Exclude specific properties | |
| Object with typed keys/values | |
| Extract function return type | |
| Extract function parameters | |
| Unwrap Promise type | |
| 类型 | 用途 | 示例 |
|---|---|---|
| 所有属性可选 | |
| 所有属性必填 | |
| 选择特定属性 | |
| 排除特定属性 | |
| 带类型键值对的对象 | |
| 提取函数返回类型 | |
| 提取函数参数类型 | |
| 解包Promise类型 | |
Conditional Types
条件类型
typescript
// Basic conditional type
type IsString<T> = T extends string ? true : false;
// Extract array element type
type ArrayElement<T> = T extends (infer E)[] ? E : never;
type Numbers = ArrayElement<number[]>; // number
type Strings = ArrayElement<string[]>; // string
// Practical: Extract Promise result type
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;typescript
// Basic conditional type
type IsString<T> = T extends string ? true : false;
// Extract array element type
type ArrayElement<T> = T extends (infer E)[] ? E : never;
type Numbers = ArrayElement<number[]>; // number
type Strings = ArrayElement<string[]>; // string
// Practical: Extract Promise result type
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;Mapped Types
映射类型
typescript
// Make all properties readonly
type Immutable<T> = {
readonly [K in keyof T]: T[K];
};
// Make all properties nullable
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
// Create getter functions for each property
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface Person { name: string; age: number }
type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number }typescript
// Make all properties readonly
type Immutable<T> = {
readonly [K in keyof T]: T[K];
};
// Make all properties nullable
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
// Create getter functions for each property
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface Person { name: string; age: number }
type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number }Framework Integration
框架集成
React with TypeScript
React与TypeScript
typescript
// Typed functional component
interface ButtonProps {
label: string;
onClick: () => void;
variant?: "primary" | "secondary";
}
const Button: React.FC<ButtonProps> = ({ label, onClick, variant = "primary" }) => (
<button className={variant} onClick={onClick}>
{label}
</button>
);
// Typed hooks
const [count, setCount] = useState<number>(0);
const userRef = useRef<HTMLInputElement>(null);typescript
// Typed functional component
interface ButtonProps {
label: string;
onClick: () => void;
variant?: "primary" | "secondary";
}
const Button: React.FC<ButtonProps> = ({ label, onClick, variant = "primary" }) => (
<button className={variant} onClick={onClick}>
{label}
</button>
);
// Typed hooks
const [count, setCount] = useState<number>(0);
const userRef = useRef<HTMLInputElement>(null);NestJS with TypeScript
NestJS与TypeScript
typescript
// Type-safe DTO with class-validator
import { IsString, IsEmail, MinLength } from 'class-validator';
class CreateUserDto {
@IsString()
@MinLength(2)
name: string;
@IsEmail()
email: string;
}
// Or with Zod (modern approach)
import { z } from 'zod';
const CreateUserSchema = z.object({
name: z.string().min(2),
email: z.string().email()
});
type CreateUserDto = z.infer<typeof CreateUserSchema>;See react-integration.md and nestjs-integration.md for detailed patterns.
typescript
// Type-safe DTO with class-validator
import { IsString, IsEmail, MinLength } from 'class-validator';
class CreateUserDto {
@IsString()
@MinLength(2)
name: string;
@IsEmail()
email: string;
}
// Or with Zod (modern approach)
import { z } from 'zod';
const CreateUserSchema = z.object({
name: z.string().min(2),
email: z.string().email()
});
type CreateUserDto = z.infer<typeof CreateUserSchema>;详细模式请查看react-integration.md和nestjs-integration.md。
Validation with Zod
Zod验证
typescript
import { z } from 'zod';
// Define schema
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
role: z.enum(["user", "admin", "moderator"]),
createdAt: z.coerce.date()
});
// Infer TypeScript type from schema
type User = z.infer<typeof UserSchema>;
// Validate at runtime
function parseUser(data: unknown): User {
return UserSchema.parse(data); // Throws ZodError if invalid
}
// Safe parsing (returns result object)
const result = UserSchema.safeParse(data);
if (result.success) {
console.log(result.data); // Typed as User
} else {
console.error(result.error.issues);
}typescript
import { z } from 'zod';
// Define schema
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
role: z.enum(["user", "admin", "moderator"]),
createdAt: z.coerce.date()
});
// Infer TypeScript type from schema
type User = z.infer<typeof UserSchema>;
// Validate at runtime
function parseUser(data: unknown): User {
return UserSchema.parse(data); // Throws ZodError if invalid
}
// Safe parsing (returns result object)
const result = UserSchema.safeParse(data);
if (result.success) {
console.log(result.data); // Typed as User
} else {
console.error(result.error.issues);
}Modern Toolchain (2025)
现代化工具链(2025)
| Tool | Version | Purpose |
|---|---|---|
| TypeScript | 5.9+ | Type checking and compilation |
| Node.js | 22 LTS | Runtime environment |
| Vite | 7.x | Build tool and dev server |
| pnpm | 9.x | Package manager |
| ESLint | 9.x | Linting with flat config |
| Vitest | 3.x | Testing framework |
| Prettier | 3.x | Code formatting |
| 工具 | 版本 | 用途 |
|---|---|---|
| TypeScript | 5.9+ | 类型检查与编译 |
| Node.js | 22 LTS | 运行环境 |
| Vite | 7.x | 构建工具与开发服务器 |
| pnpm | 9.x | 包管理器 |
| ESLint | 9.x | 代码检查(扁平配置) |
| Vitest | 3.x | 测试框架 |
| Prettier | 3.x | 代码格式化 |
ESLint Flat Config (ESLint 9+)
ESLint扁平配置(ESLint 9+)
javascript
// eslint.config.js
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
}
);javascript
// eslint.config.js
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
}
);Migration Strategies
迁移策略
Incremental Migration
增量迁移
- Add and
allowJs: trueto tsconfig.jsoncheckJs: false - Rename files from to
.jsone at a time.ts - Add type annotations gradually
- Enable stricter options incrementally
- 在tsconfig.json中添加和
allowJs: truecheckJs: false - 逐个将文件从重命名为
.js.ts - 逐步添加类型注解
- 逐步启用更严格的配置选项
JSDoc for Gradual Typing
使用JSDoc实现渐进式类型化
javascript
// Before full migration, use JSDoc
/**
* @param {string} name
* @param {number} age
* @returns {User}
*/
function createUser(name, age) {
return { name, age };
}See enterprise-patterns.md for comprehensive migration guides.
javascript
// Before full migration, use JSDoc
/**
* @param {string} name
* @param {number} age
* @returns {User}
*/
function createUser(name, age) {
return { name, age };
}完整迁移指南请查看enterprise-patterns.md。
Common Mistakes
常见错误
| Mistake | Problem | Fix |
|---|---|---|
Using | Defeats type safety | Use |
| Ignoring strict mode | Misses null/undefined bugs | Enable all strict options |
Type assertions ( | Can hide type errors | Use |
| Enum for simple unions | Generates runtime code | Use literal unions instead |
| Not validating API data | Runtime type mismatches | Use Zod at boundaries |
| 错误 | 问题 | 解决方法 |
|---|---|---|
大量使用 | 失去类型安全性 | 使用 |
| 忽略严格模式 | 遗漏null/undefined相关bug | 启用所有严格配置选项 |
类型断言( | 可能隐藏类型错误 | 使用 |
| 对简单联合类型使用Enum | 生成运行时代码 | 使用字面量联合类型替代 |
| 不验证API数据 | 运行时类型不匹配 | 在边界处使用Zod验证 |
Cross-Language Comparison
跨语言对比
| Feature | TypeScript | Java | Python |
|---|---|---|---|
| Type System | Structural | Nominal | Gradual (duck typing) |
| Nullability | Explicit ( | | Optional via typing |
| Generics | Type-level, erased | Type-level, erased | Runtime via typing |
| Interfaces | Structural matching | Must implement | Protocol (3.8+) |
| Enums | Avoid (use unions) | First-class | Enum class |
| 特性 | TypeScript | Java | Python |
|---|---|---|---|
| 类型系统 | 结构化 | 标称式 | 渐进式(鸭子类型) |
| 空值处理 | 显式( | | 通过类型系统可选 |
| 泛型 | 类型层面,编译后擦除 | 类型层面,编译后擦除 | 运行时通过类型系统实现 |
| 接口 | 结构匹配 | 必须显式实现 | 协议(3.8+) |
| 枚举 | 建议避免(使用联合类型) | 一等公民 | 枚举类 |
Reference Files
参考文件
- type-system.md — Complete type system guide
- generics.md — Advanced generics patterns
- enterprise-patterns.md — Error handling, validation, architecture
- react-integration.md — React + TypeScript patterns
- nestjs-integration.md — NestJS API development
- toolchain.md — Modern build tools configuration
- type-system.md — 完整类型系统指南
- generics.md — 高级泛型模式
- enterprise-patterns.md — 错误处理、验证、架构
- react-integration.md — React + TypeScript模式
- nestjs-integration.md — NestJS API开发
- toolchain.md — 现代化构建工具配置
Assets
资源文件
- tsconfig-template.json — Strict enterprise config
- eslint-template.js — ESLint 9 flat config
- tsconfig-template.json — 严格企业级配置
- eslint-template.js — ESLint 9扁平配置
Scripts
脚本
- validate-setup.sh — Verify TypeScript environment
- validate-setup.sh — 验证TypeScript环境