logoAI Saas
Home
Blog
Documentation
Blocks
Pricing
Contact
返回博客列表

TypeScript Advanced Patterns and Techniques

Deep dive into TypeScript's advanced features and practical patterns

约5分钟阅读

TypeScript Advanced Patterns and Techniques

TypeScript is more than just type annotations for JavaScript—it provides a powerful type system and advanced features. This article will explore some practical TypeScript advanced patterns.

实用类型(Utility Types)

1. Pick 和 Omit

interface User {
  id: string;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
}

// 只选择特定字段
type PublicUser = Pick<User, 'id' | 'name' | 'email'>;

// 排除特定字段
type CreateUserInput = Omit<User, 'id' | 'createdAt'>;

// 实际使用
function getPublicUserInfo(user: User): PublicUser {
  return {
    id: user.id,
    name: user.name,
    email: user.email,
  };
}

2. Partial 和 Required

interface Config {
  apiUrl: string;
  timeout: number;
  retries: number;
}

// 所有字段都是可选的
type PartialConfig = Partial<Config>;

// 所有字段都是必需的
type RequiredConfig = Required<PartialConfig>;

function updateConfig(config: PartialConfig): void {
  // 只更新提供的字段
}

条件类型(Conditional Types)

基础条件类型

type IsString<T> = T extends string ? true : false;

type Test1 = IsString<string>; // true
type Test2 = IsString<number>; // false

// 实用的条件类型
type NonNullable<T> = T extends null | undefined ? never : T;

type ApiResponse<T> = T extends string
  ? { message: T }
  : T extends number
  ? { code: T }
  : { data: T };

分布式条件类型

type ToArray<T> = T extends any ? T[] : never;

type StringOrNumberArray = ToArray<string | number>;
// 结果:string[] | number[]

// 过滤类型
type Filter<T, U> = T extends U ? T : never;

type StringsOnly = Filter<string | number | boolean, string>;
// 结果:string

映射类型(Mapped Types)

基础映射类型

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

type Optional<T> = {
  [P in keyof T]?: T[P];
};

// 添加前缀
type Prefixed<T, P extends string> = {
  [K in keyof T as `${P}${string & K}`]: T[K];
};

interface User {
  name: string;
  age: number;
}

type PrefixedUser = Prefixed<User, 'user_'>;
// 结果:{ user_name: string; user_age: number; }

高级映射类型

// 深度只读
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

// 键值对转换
type Record<K extends keyof any, T> = {
  [P in K]: T;
};

// 创建事件处理器类型
type EventHandlers<T> = {
  [K in keyof T as `on${Capitalize<string & K>}`]: (value: T[K]) => void;
};

interface FormData {
  name: string;
  email: string;
  age: number;
}

type FormHandlers = EventHandlers<FormData>;
// 结果:{
//   onName: (value: string) => void;
//   onEmail: (value: string) => void;
//   onAge: (value: number) => void;
// }

模板字面量类型

基础用法

type Greeting = `Hello, ${string}!`;

const greeting1: Greeting = "Hello, World!"; // ✅
const greeting2: Greeting = "Hi there!"; // ❌

// 组合类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = `/api/${string}`;
type ApiCall = `${HttpMethod} ${Endpoint}`;

const apiCall: ApiCall = "GET /api/users"; // ✅

高级模板类型

// 路径参数提取
type ExtractParams<T extends string> = T extends `${string}:${infer P}/${infer Rest}`
  ? P | ExtractParams<Rest>
  : T extends `${string}:${infer P}`
  ? P
  : never;

type Params = ExtractParams<'/users/:id/posts/:postId'>;
// 结果:'id' | 'postId'

// SQL 查询构建器
type SelectQuery<T, K extends keyof T> = `SELECT ${K extends string ? K : never} FROM ${string}`;

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

type UserQuery = SelectQuery<User, 'name' | 'email'>;
// 结果:'SELECT name FROM string' | 'SELECT email FROM string'

高级函数类型

函数重载

interface ApiClient {
  request(method: 'GET', url: string): Promise<any>;
  request(method: 'POST', url: string, data: any): Promise<any>;
  request(method: 'PUT', url: string, data: any): Promise<any>;
  request(method: 'DELETE', url: string): Promise<any>;
}

class HttpClient implements ApiClient {
  async request(method: string, url: string, data?: any): Promise<any> {
    // 实现逻辑
  }
}

泛型约束

interface Lengthwise {
  length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

logLength("hello"); // ✅
logLength([1, 2, 3]); // ✅
logLength(123); // ❌ 没有 length 属性

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

const person = { name: "Alice", age: 30 };
const name = getProperty(person, "name"); // string
const age = getProperty(person, "age"); // number

装饰器模式

类装饰器

function Entity(tableName: string) {
  return function <T extends { new (...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
      tableName = tableName;
    };
  };
}

@Entity('users')
class User {
  constructor(public name: string) {}
}

// 方法装饰器
function Log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
  const method = descriptor.value;
  
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyName} with args:`, args);
    const result = method.apply(this, args);
    console.log(`Result:`, result);
    return result;
  };
}

class Calculator {
  @Log
  add(a: number, b: number): number {
    return a + b;
  }
}

类型守卫(Type Guards)

自定义类型守卫

interface Cat {
  type: 'cat';
  meow(): void;
}

interface Dog {
  type: 'dog';
  bark(): void;
}

type Animal = Cat | Dog;

// 类型谓词
function isCat(animal: Animal): animal is Cat {
  return animal.type === 'cat';
}

function makeSound(animal: Animal) {
  if (isCat(animal)) {
    animal.meow(); // TypeScript 知道这是 Cat
  } else {
    animal.bark(); // TypeScript 知道这是 Dog
  }
}

// 断言函数
function assertIsNumber(value: unknown): asserts value is number {
  if (typeof value !== 'number') {
    throw new Error('Expected number');
  }
}

function processValue(value: unknown) {
  assertIsNumber(value);
  // 这里 TypeScript 知道 value 是 number
  console.log(value.toFixed(2));
}

模块声明和命名空间

环境声明

// global.d.ts
declare global {
  interface Window {
    gtag: (command: string, ...args: any[]) => void;
  }
  
  var ENV: 'development' | 'production' | 'test';
}

// 模块声明
declare module '*.svg' {
  const content: string;
  export default content;
}

declare module 'my-library' {
  export function doSomething(value: string): number;
}

命名空间

namespace Utils {
  export namespace String {
    export function capitalize(str: string): string {
      return str.charAt(0).toUpperCase() + str.slice(1);
    }
    
    export function truncate(str: string, length: number): string {
      return str.length > length ? str.slice(0, length) + '...' : str;
    }
  }
  
  export namespace Array {
    export function unique<T>(arr: T[]): T[] {
      return [...new Set(arr)];
    }
  }
}

// 使用
const capitalized = Utils.String.capitalize('hello');
const uniqueItems = Utils.Array.unique([1, 2, 2, 3]);

实际应用示例

API 客户端类型安全

interface ApiEndpoints {
  '/users': {
    GET: { response: User[] };
    POST: { body: CreateUserInput; response: User };
  };
  '/users/:id': {
    GET: { response: User };
    PUT: { body: UpdateUserInput; response: User };
    DELETE: { response: void };
  };
}

type ExtractPath<T extends string> = T extends `${infer Path}/:${string}`
  ? Path
  : T;

class TypedApiClient {
  async request<
    Path extends keyof ApiEndpoints,
    Method extends keyof ApiEndpoints[Path]
  >(
    method: Method,
    path: Path,
    options?: ApiEndpoints[Path][Method] extends { body: infer B }
      ? { body: B }
      : {}
  ): Promise<
    ApiEndpoints[Path][Method] extends { response: infer R } ? R : never
  > {
    // 实现逻辑
    throw new Error('Not implemented');
  }
}

// 使用时具有完整的类型安全
const client = new TypedApiClient();
const users = await client.request('GET', '/users'); // User[]
const user = await client.request('POST', '/users', {
  body: { name: 'Alice', email: '[email protected]' }
}); // User

总结

TypeScript 的高级特性为我们提供了强大的类型系统工具:

  1. 实用类型:简化常见的类型操作
  2. 条件类型:基于条件的类型选择
  3. 映射类型:类型转换和操作
  4. 模板字面量:字符串类型的精确控制
  5. 类型守卫:运行时类型检查
  6. 装饰器:元编程支持

掌握这些高级模式可以让你编写更安全、更可维护的 TypeScript 代码,充分发挥类型系统的优势。

分享这篇文章

返回博客
AI SAAS

基于 Next.js 15 和 React 19 构建的现代化 AI SAAS 平台

产品

  • 定价
  • 文档

支持

  • 联系我们
  • 隐私政策

© 2024 AI SAAS. All rights reserved.