developing-with-typescript

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TypeScript Development Skill

TypeScript 开发技能

TypeScript 5.x development with modern patterns including strict mode, generics, utility types, and modules.
Progressive Disclosure: Quick reference patterns here. See REFERENCE.md for advanced topics.

涵盖严格模式、泛型、工具类型、模块等现代开发模式的 TypeScript 5.x 开发指南。
渐进式内容展示:此处提供快速参考模式,高级主题请查看REFERENCE.md

When to Use

适用场景

Loaded by
backend-developer
or
frontend-developer
when:
  • tsconfig.json
    present in project
  • package.json
    contains
    typescript
    dependency
  • .ts
    or
    .tsx
    files in project

满足以下条件时,会被
backend-developer
frontend-developer
自动加载:
  • 项目中存在
    tsconfig.json
    文件
  • package.json
    包含
    typescript
    依赖
  • 项目中存在
    .ts
    .tsx
    文件

Quick Start

快速开始

Basic Types

基础类型

typescript
// Primitives
const name: string = "Alice";
const age: number = 30;
const isActive: boolean = true;

// Arrays and Tuples
const numbers: number[] = [1, 2, 3];
const point: [number, number] = [10, 20];
const rest: [string, ...number[]] = ["scores", 1, 2, 3];
typescript
// Primitives
const name: string = "Alice";
const age: number = 30;
const isActive: boolean = true;

// Arrays and Tuples
const numbers: number[] = [1, 2, 3];
const point: [number, number] = [10, 20];
const rest: [string, ...number[]] = ["scores", 1, 2, 3];

Interfaces vs Type Aliases

接口与类型别名对比

typescript
// Interfaces - object shapes, extensible, declaration merging
interface User {
  id: string;
  name: string;
  email: string;
}

interface Admin extends User {
  permissions: string[];
}

// Type aliases - unions, tuples, primitives, complex types
type ID = string | number;
type Point = [number, number];
type Callback = (data: string) => void;
type AdminUser = User & { permissions: string[] };
typescript
// Interfaces - object shapes, extensible, declaration merging
interface User {
  id: string;
  name: string;
  email: string;
}

interface Admin extends User {
  permissions: string[];
}

// Type aliases - unions, tuples, primitives, complex types
type ID = string | number;
type Point = [number, number];
type Callback = (data: string) => void;
type AdminUser = User & { permissions: string[] };

Functions

函数

typescript
// Basic function
function greet(name: string): string {
  return `Hello, ${name}`;
}

// Arrow with optional/default params
const createUser = (name: string, age?: number, role = "user") => ({ name, age, role });

// Function overloads
function parse(input: string): string[];
function parse(input: string[]): string;
function parse(input: string | string[]): string | string[] {
  return typeof input === "string" ? input.split(",") : input.join(",");
}

typescript
// Basic function
function greet(name: string): string {
  return `Hello, ${name}`;
}

// Arrow with optional/default params
const createUser = (name: string, age?: number, role = "user") => ({ name, age, role });

// Function overloads
function parse(input: string): string[];
function parse(input: string[]): string;
function parse(input: string | string[]): string | string[] {
  return typeof input === "string" ? input.split(",") : input.join(",");
}

Type System Essentials

类型系统核心要点

Union and Intersection Types

联合类型与交叉类型

typescript
// Union - one of multiple types
type Status = "pending" | "approved" | "rejected";
type Result = string | Error;

// Intersection - combine types
type Timestamped = { createdAt: Date; updatedAt: Date };
type Entity = User & Timestamped;
typescript
// Union - one of multiple types
type Status = "pending" | "approved" | "rejected";
type Result = string | Error;

// Intersection - combine types
type Timestamped = { createdAt: Date; updatedAt: Date };
type Entity = User & Timestamped;

Literal Types

字面量类型

typescript
type Direction = "north" | "south" | "east" | "west";
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;

// Template literal types
type EventName = `on${Capitalize<string>}`;
type Getter<T extends string> = `get${Capitalize<T>}`;
typescript
type Direction = "north" | "south" | "east" | "west";
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;

// Template literal types
type EventName = `on${Capitalize<string>}`;
type Getter<T extends string> = `get${Capitalize<T>}`;

Type Narrowing

类型收窄

typescript
// typeof guard
function format(value: string | number): string {
  return typeof value === "string" ? value.trim() : value.toFixed(2);
}

// in operator
function speak(animal: { bark(): void } | { meow(): void }): void {
  if ("bark" in animal) animal.bark();
  else animal.meow();
}

// Discriminated unions (recommended)
type Success = { status: "success"; data: string };
type Failure = { status: "failure"; error: Error };
type Result = Success | Failure;

function handle(result: Result): string {
  return result.status === "success" ? result.data : result.error.message;
}

typescript
// typeof guard
function format(value: string | number): string {
  return typeof value === "string" ? value.trim() : value.toFixed(2);
}

// in operator
function speak(animal: { bark(): void } | { meow(): void }): void {
  if ("bark" in animal) animal.bark();
  else animal.meow();
}

// Discriminated unions (recommended)
type Success = { status: "success"; data: string };
type Failure = { status: "failure"; error: Error };
type Result = Success | Failure;

function handle(result: Result): string {
  return result.status === "success" ? result.data : result.error.message;
}

Generics

泛型

Basic Generics

基础泛型

typescript
function identity<T>(value: T): T {
  return value;
}

interface Box<T> {
  value: T;
  map<U>(fn: (value: T) => U): Box<U>;
}

class Container<T> {
  constructor(private value: T) {}
  get(): T { return this.value; }
}
typescript
function identity<T>(value: T): T {
  return value;
}

interface Box<T> {
  value: T;
  map<U>(fn: (value: T) => U): Box<U>;
}

class Container<T> {
  constructor(private value: T) {}
  get(): T { return this.value; }
}

Constraints

泛型约束

typescript
// extends constraint
function getLength<T extends { length: number }>(item: T): number {
  return item.length;
}

// keyof constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// Default type
interface ApiResponse<T = unknown> {
  data: T;
  status: number;
}

typescript
// extends constraint
function getLength<T extends { length: number }>(item: T): number {
  return item.length;
}

// keyof constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// Default type
interface ApiResponse<T = unknown> {
  data: T;
  status: number;
}

Utility Types

工具类型

Transformation

类型转换

typescript
interface User {
  id: string;
  name: string;
  email: string;
  age: number;
}

type PartialUser = Partial<User>;           // All optional
type RequiredUser = Required<PartialUser>;  // All required
type ReadonlyUser = Readonly<User>;         // All readonly

type UserPreview = Pick<User, "id" | "name">;
type UserWithoutEmail = Omit<User, "email">;

type UserRoles = Record<string, "admin" | "user">;
typescript
interface User {
  id: string;
  name: string;
  email: string;
  age: number;
}

type PartialUser = Partial<User>;           // All optional
type RequiredUser = Required<PartialUser>;  // All required
type ReadonlyUser = Readonly<User>;         // All readonly

type UserPreview = Pick<User, "id" | "name">;
type UserWithoutEmail = Omit<User, "email">;

type UserRoles = Record<string, "admin" | "user">;

Extraction

类型提取

typescript
// Extract/Exclude from unions
type Numbers = Extract<string | number | boolean, number>;  // number
type NotNumber = Exclude<string | number | boolean, number>; // string | boolean

// Remove null/undefined
type Defined = NonNullable<string | null | undefined>;  // string

// Function types
type Return = ReturnType<typeof createUser>;
type Params = Parameters<typeof createUser>;

// Unwrap Promise
type Unwrapped = Awaited<Promise<string>>;  // string

typescript
// Extract/Exclude from unions
type Numbers = Extract<string | number | boolean, number>;  // number
type NotNumber = Exclude<string | number | boolean, number>; // string | boolean

// Remove null/undefined
type Defined = NonNullable<string | null | undefined>;  // string

// Function types
type Return = ReturnType<typeof createUser>;
type Params = Parameters<typeof createUser>;

// Unwrap Promise
type Unwrapped = Awaited<Promise<string>>;  // string

tsconfig.json Essentials

tsconfig.json 核心配置

Recommended Strict Config

推荐严格模式配置

json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "declaration": true,
    "outDir": "./dist",
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "declaration": true,
    "outDir": "./dist",
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Key Strict Flags

核心严格模式配置项

FlagPurpose
strict
Enable all strict checks
noImplicitAny
Error on implicit any
strictNullChecks
null/undefined require handling
noUncheckedIndexedAccess
Index access may be undefined

配置项作用
strict
启用所有严格检查
noImplicitAny
隐式 any 类型会抛出错误
strictNullChecks
必须处理 null/undefined 类型
noUncheckedIndexedAccess
索引访问的结果可能为 undefined

Module Patterns

模块模式

Import/Export

导入/导出

typescript
// Named exports
export const PI = 3.14159;
export function calculate(r: number): number { return PI * r ** 2; }
export interface Circle { radius: number; }

// Default export
export default class Calculator { }

// Re-exports
export { User } from "./user";
export * from "./utils";

// Type-only imports
import type { User } from "./types";
export type { Config } from "./config";
typescript
// Named exports
export const PI = 3.14159;
export function calculate(r: number): number { return PI * r ** 2; }
export interface Circle { radius: number; }

// Default export
export default class Calculator { }

// Re-exports
export { User } from "./user";
export * from "./utils";

// Type-only imports
import type { User } from "./types";
export type { Config } from "./config";

Declaration Files

声明文件

typescript
// types.d.ts
declare module "untyped-library" {
  export function process(input: string): string;
}

// Extend existing module
declare module "express" {
  interface Request { userId?: string; }
}

// Global declarations
declare global {
  interface Window { myApp: { version: string }; }
}

typescript
// types.d.ts
declare module "untyped-library" {
  export function process(input: string): string;
}

// Extend existing module
declare module "express" {
  interface Request { userId?: string; }
}

// Global declarations
declare global {
  interface Window { myApp: { version: string }; }
}

Common Patterns

常用模式

Type Guards

类型守卫

typescript
// User-defined type guard
function isString(value: unknown): value is string {
  return typeof value === "string";
}

function isUser(obj: unknown): obj is User {
  return typeof obj === "object" && obj !== null && "id" in obj && "name" in obj;
}

// Assertion function
function assertDefined<T>(value: T | undefined): asserts value is T {
  if (value === undefined) throw new Error("Value is undefined");
}
typescript
// User-defined type guard
function isString(value: unknown): value is string {
  return typeof value === "string";
}

function isUser(obj: unknown): obj is User {
  return typeof obj === "object" && obj !== null && "id" in obj && "name" in obj;
}

// Assertion function
function assertDefined<T>(value: T | undefined): asserts value is T {
  if (value === undefined) throw new Error("Value is undefined");
}

Branded Types

品牌类型

typescript
// Prevent type confusion
type UserId = string & { readonly brand: unique symbol };
type OrderId = string & { readonly brand: unique symbol };

function createUserId(id: string): UserId { return id as UserId; }
function createOrderId(id: string): OrderId { return id as OrderId; }

function getUser(id: UserId): User { /* ... */ }

const userId = createUserId("user-123");
getUser(userId);  // OK
// getUser(createOrderId("order-456"));  // Error!
typescript
// Prevent type confusion
type UserId = string & { readonly brand: unique symbol };
type OrderId = string & { readonly brand: unique symbol };

function createUserId(id: string): UserId { return id as UserId; }
function createOrderId(id: string): OrderId { return id as OrderId; }

function getUser(id: UserId): User { /* ... */ }

const userId = createUserId("user-123");
getUser(userId);  // OK
// getUser(createOrderId("order-456"));  // Error!

Result Type

结果类型

typescript
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

function divide(a: number, b: number): Result<number, string> {
  if (b === 0) return { success: false, error: "Division by zero" };
  return { success: true, data: a / b };
}

const result = divide(10, 2);
if (result.success) console.log(result.data);
else console.error(result.error);

typescript
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

function divide(a: number, b: number): Result<number, string> {
  if (b === 0) return { success: false, error: "Division by zero" };
  return { success: true, data: a / b };
}

const result = divide(10, 2);
if (result.success) console.log(result.data);
else console.error(result.error);

Quick Reference

快速参考

Assertions

类型断言

typescript
const value = someValue as string;           // Type assertion
const element = document.getElementById("app")!;  // Non-null assertion
const config = { api: "/api" } as const;     // Const assertion
typescript
const value = someValue as string;           // Type assertion
const element = document.getElementById("app")!;  // Non-null assertion
const config = { api: "/api" } as const;     // Const assertion

Index Signatures

索引签名

typescript
interface StringMap { [key: string]: string; }
interface NumberMap { [index: number]: string; }
interface DataAttrs { [key: `data-${string}`]: string; }
typescript
interface StringMap { [key: string]: string; }
interface NumberMap { [index: number]: string; }
interface DataAttrs { [key: `data-${string}`]: string; }

Mapped Types

映射类型

typescript
type Optional<T> = { [K in keyof T]?: T[K] };
type Immutable<T> = { readonly [K in keyof T]: T[K] };
type Mutable<T> = { -readonly [K in keyof T]: T[K] };

typescript
type Optional<T> = { [K in keyof T]?: T[K] };
type Immutable<T> = { readonly [K in keyof T]: T[K] };
type Mutable<T> = { -readonly [K in keyof T]: T[K] };

See Also

参考资料