mastering-typescript

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Mastering 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
undefined
bash
undefined

Initialize 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
undefined
cat > tsconfig.json << 'EOF' { "compilerOptions": { "target": "ES2024", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "esModuleInterop": true, "skipLibCheck": true } } EOF
undefined

When 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+)

satisfies
操作符(TS 5.0+)

Validate 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 exists

Generics 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 | undefined
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 | undefined

Constrained 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 length
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 length

Generic 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

工具类型参考

TypePurposeExample
Partial<T>
All properties optional
Partial<User>
Required<T>
All properties required
Required<Config>
Pick<T, K>
Select specific properties
Pick<User, "id" | "name">
Omit<T, K>
Exclude specific properties
Omit<User, "password">
Record<K, V>
Object with typed keys/values
Record<string, number>
ReturnType<F>
Extract function return type
ReturnType<typeof fn>
Parameters<F>
Extract function parameters
Parameters<typeof fn>
Awaited<T>
Unwrap Promise type
Awaited<Promise<User>>
类型用途示例
Partial<T>
所有属性可选
Partial<User>
Required<T>
所有属性必填
Required<Config>
Pick<T, K>
选择特定属性
Pick<User, "id" | "name">
Omit<T, K>
排除特定属性
Omit<User, "password">
Record<K, V>
带类型键值对的对象
Record<string, number>
ReturnType<F>
提取函数返回类型
ReturnType<typeof fn>
Parameters<F>
提取函数参数类型
Parameters<typeof fn>
Awaited<T>
解包Promise类型
Awaited<Promise<User>>

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.mdnestjs-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)

ToolVersionPurpose
TypeScript5.9+Type checking and compilation
Node.js22 LTSRuntime environment
Vite7.xBuild tool and dev server
pnpm9.xPackage manager
ESLint9.xLinting with flat config
Vitest3.xTesting framework
Prettier3.xCode formatting
工具版本用途
TypeScript5.9+类型检查与编译
Node.js22 LTS运行环境
Vite7.x构建工具与开发服务器
pnpm9.x包管理器
ESLint9.x代码检查(扁平配置)
Vitest3.x测试框架
Prettier3.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

增量迁移

  1. Add
    allowJs: true
    and
    checkJs: false
    to tsconfig.json
  2. Rename files from
    .js
    to
    .ts
    one at a time
  3. Add type annotations gradually
  4. Enable stricter options incrementally
  1. 在tsconfig.json中添加
    allowJs: true
    checkJs: false
  2. 逐个将文件从
    .js
    重命名为
    .ts
  3. 逐步添加类型注解
  4. 逐步启用更严格的配置选项

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

常见错误

MistakeProblemFix
Using
any
liberally
Defeats type safetyUse
unknown
and narrow
Ignoring strict modeMisses null/undefined bugsEnable all strict options
Type assertions (
as
)
Can hide type errorsUse
satisfies
or guards
Enum for simple unionsGenerates runtime codeUse literal unions instead
Not validating API dataRuntime type mismatchesUse Zod at boundaries
错误问题解决方法
大量使用
any
失去类型安全性使用
unknown
并进行类型收窄
忽略严格模式遗漏null/undefined相关bug启用所有严格配置选项
类型断言(
as
可能隐藏类型错误使用
satisfies
或类型守卫
对简单联合类型使用Enum生成运行时代码使用字面量联合类型替代
不验证API数据运行时类型不匹配在边界处使用Zod验证

Cross-Language Comparison

跨语言对比

FeatureTypeScriptJavaPython
Type SystemStructuralNominalGradual (duck typing)
NullabilityExplicit (
T | null
)
@Nullable
annotations
Optional via typing
GenericsType-level, erasedType-level, erasedRuntime via typing
InterfacesStructural matchingMust implementProtocol (3.8+)
EnumsAvoid (use unions)First-classEnum class
特性TypeScriptJavaPython
类型系统结构化标称式渐进式(鸭子类型)
空值处理显式(
T | null
@Nullable
注解
通过类型系统可选
泛型类型层面,编译后擦除类型层面,编译后擦除运行时通过类型系统实现
接口结构匹配必须显式实现协议(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环境