技术
10 min read

TypeScript 高级类型系统:从基础到精通

2025-01-18by LZG
#TypeScript#Frontend#Engineering

引言

TypeScript 的类型系统是其最强大的特性之一。从基础类型到高级类型,掌握这些概念可以帮助我们编写更安全、更可维护的代码。

1. 泛型 (Generics)

1.1 基础泛型

泛型允许我们编写可重用的组件,同时保持类型安全。

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

const num = identity<number>(42);
const str = identity("hello");

1.2 泛型约束

interface Lengthwise {
  length: number;
}

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

1.3 泛型接口

interface Box<T> {
  value: T;
}

const box: Box<string> = { value: "hello" };

2. 条件类型 (Conditional Types)

条件类型允许我们根据类型关系选择不同的类型。

2.1 基础语法

type IsArray<T> = T extends any[] ? true : false;

type A = IsArray<string[]>; // true
type B = IsArray<string>;   // false

2.2 分布式条件类型

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

type StrArrOrNumArr = ToArray<string | number>;
// string[] | number[]

2.3 条件类型推断

type Flatten<T> = T extends infer U[] ? U : T;

type Flat = Flatten<number[][]>; // number

3. 映射类型 (Mapped Types)

映射类型允许我们基于现有类型创建新类型。

3.1 基础映射

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

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

type ReadonlyUser = Readonly<User>;

3.2 添加修饰符

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

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

3.3 Key Remapping

type Getters<T> = {
  [P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
};

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

type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number }

4. 模板字面量类型

4.1 基础用法

type EventName<T extends string> = `on${Capitalize<T>}`;

type ClickEvent = EventName<"click">; // "onClick"

4.2 字符串操作类型

type Greeting<T extends string> = `Hello, ${T}!`;

type Message = Greeting<"World">; // "Hello, World!"

5. 实用工具类型

5.1 Pick 和 Omit

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

type PublicUser = Pick<User, "id" | "name" | "email">;
type SafeUser = Omit<User, "password">;

5.2 Record

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

const roles: UserRoles = {
  alice: "admin",
  bob: "user",
};

5.3 ReturnType

function getUser() {
  return { id: 1, name: "Alice" };
}

type User = ReturnType<typeof getUser>;

6. 高级模式

6.1 递归类型

type Json = 
  | string 
  | number 
  | boolean 
  | null 
  | Json[] 
  | { [key: string]: Json };

const data: Json = {
  name: "Alice",
  age: 30,
  tags: ["developer", "typescript"],
};

6.2 品牌类型

type Brand<T, B> = T & { __brand: B };

type USD = Brand<number, "USD">;
type EUR = Brand<number, "EUR">;

const usdAmount: USD = 100 as USD;
const eurAmount: EUR = 100 as EUR;

// 类型安全:不能直接相加
// const total = usdAmount + eurAmount; // Error

6.3 函数重载

function process(input: string): string;
function process(input: number): number;
function process(input: string | number): string | number {
  if (typeof input === "string") {
    return input.toUpperCase();
  }
  return input * 2;
}

7. 类型守卫

7.1 typeof 守卫

function processValue(value: string | number) {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

7.2 instanceof 守卫

class Dog {
  bark() { console.log("Woof!"); }
}

class Cat {
  meow() { console.log("Meow!"); }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark();
  } else {
    animal.meow();
  }
}

7.3 自定义类型守卫

interface Bird {
  type: "bird";
  fly(): void;
}

interface Fish {
  type: "fish";
  swim(): void;
}

function isBird(animal: Bird | Fish): animal is Bird {
  return animal.type === "bird";
}

function move(animal: Bird | Fish) {
  if (isBird(animal)) {
    animal.fly();
  } else {
    animal.swim();
  }
}

8. 实战案例

8.1 API 响应类型

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

async function fetchUser(id: number): Promise<ApiResponse<User>> {
  try {
    const user = await api.getUser(id);
    return { success: true, data: user };
  } catch (error) {
    return { success: false, error: error as Error };
  }
}

8.2 表单验证类型

type ValidationRule<T> = {
  validate: (value: T) => boolean;
  message: string;
};

type FormField<T> = {
  value: T;
  rules: ValidationRule<T>[];
};

type FormSchema<T extends Record<string, any>> = {
  [K in keyof T]: FormField<T[K]>;
};

结语

TypeScript 的高级类型系统为我们提供了强大的类型安全能力。通过掌握泛型、条件类型、映射类型等概念,我们可以编写出更加健壮和可维护的代码。关键是在实际项目中灵活运用这些技术,找到类型安全和开发效率的最佳平衡点。