VVLL.net

Advanced Topics(高级主题)

日期:2024-08-22 09:58:31

TypeScript 高级类型

TypeScript 高级类型是 TypeScript 类型系统中的一些高级特性和技巧,用于编写更复杂和灵活的代码。以下是 TypeScript 高级类型的详细介绍,包括交叉类型、联合类型、类型别名、类型断言、字面量类型、可辨识联合、类型守卫、映射类型和条件类型。

1. 交叉类型(Intersection Types)

交叉类型 A & B 表示同时是 AB 类型的类型。它通常用于将多个类型的成员结合在一起。

interface Person {
  name: string;
}

interface Employee {
  employeeId: number;
}

type Staff = Person & Employee;

const staffMember: Staff = {
  name: "John",
  employeeId: 123
};

2. 联合类型(Union Types)

联合类型 A | B 表示可以是 AB 类型的类型。它通常用于表示一个值可以有多种类型。

function printId(id: number | string) {
  console.log(`ID: ${id}`);
}

printId(123);
printId("abc");

3. 类型别名(Type Aliases)

类型别名用于给类型起一个新的名字。它可以简化复杂类型的使用。

type StringOrNumber = string | number;

let value: StringOrNumber;
value = "hello";
value = 42;

4. 字面量类型(Literal Types)

字面量类型允许你指定一个变量只能有特定的值。它通常与联合类型结合使用来实现枚举的效果。

type Direction = "up" | "down" | "left" | "right";

function move(direction: Direction) {
  console.log(`Moving ${direction}`);
}

move("up");
// move("forward"); // Error: Argument of type '"forward"' is not assignable to parameter of type 'Direction'.

5. 可辨识联合(Discriminated Unions)

可辨识联合是 TypeScript 中的一种模式,用于类型安全地处理联合类型。它通常由联合类型、字面量类型和类型守卫结合实现。

interface Square {
  kind: "square";
  size: number;
}

interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}

interface Circle {
  kind: "circle";
  radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(shape: Shape): number {
  switch (shape.kind) {
    case "square":
      return shape.size * shape.size;
    case "rectangle":
      return shape.width * shape.height;
    case "circle":
      return Math.PI * shape.radius * shape.radius;
    default:
      return 0;
  }
}

6. 类型守卫(Type Guards)

类型守卫是一些表达式,用于在运行时检查类型,并在特定的代码块中缩小类型范围。常见的类型守卫包括 typeofinstanceof 和自定义类型谓词。

function isString(value: any): value is string {
  return typeof value === "string";
}

function print(value: string | number) {
  if (isString(value)) {
    console.log(`String: ${value}`);
  } else {
    console.log(`Number: ${value}`);
  }
}

7. 映射类型(Mapped Types)

映射类型用于基于旧类型创建新类型。它遍历旧类型的属性,并基于其创建新的类型。

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

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

type ReadonlyPerson = Readonly<Person>;

const person: ReadonlyPerson = { name: "Alice", age: 30 };
// person.age = 31; // Error: Cannot assign to 'age' because it is a read-only property.

8. 条件类型(Conditional Types)

条件类型用于根据某个条件表达式生成不同的类型。

type TypeName<T> = T extends string
  ? "string"
  : T extends number
  ? "number"
  : T extends boolean
  ? "boolean"
  : T extends undefined
  ? "undefined"
  : T extends Function
  ? "function"
  : "object";

type T1 = TypeName<string>;  // "string"
type T2 = TypeName<number>;  // "number"
type T3 = TypeName<boolean>; // "boolean"
type T4 = TypeName<() => void>; // "function"
type T5 = TypeName<object>; // "object"

9. 索引类型(Index Types)

定义:索引类型用于获取对象属性的类型。

用法:使用 keyof 和索引访问操作符 T[K]

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

type PersonKeys = keyof Person; // "name" | "age"

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

let person: Person = { name: "Alice", age: 30 };
let name: string = getValue(person, "name"); // OK
// let invalid = getValue(person, "invalid"); // Error: Argument of type '"invalid"' is not assignable to parameter of type 'keyof Person'.

说明keyof 操作符获取对象的键,T[K] 获取对象属性的类型。

高级类型示例

结合使用多个高级类型特性可以创建更复杂的类型定义。

type ApiResponse<T> = {
  data: T;
  error: string | null;
  status: number;
};

type User = {
  id: number;
  name: string;
  email: string;
};

type UserResponse = ApiResponse<User>;

const response: UserResponse = {
  data: { id: 1, name: "John Doe", email: "john.doe@example.com" },
  error: null,
  status: 200,
};

高级类型总结

TypeScript 高级类型提供了一些强大而灵活的工具,用于创建复杂且类型安全的代码。通过理解和利用这些特性,你可以编写更健壮和可维护的 TypeScript 代码。以下是关键点:

  • 交叉类型:将多个类型合并为一个类型。
  • 联合类型:表示值可以是多种类型之一。
  • 类型别名:给复杂类型起一个简洁的名字。
  • 字面量类型:指定变量只能有特定的值。
  • 可辨识联合:安全处理联合类型。
  • 类型守卫:在运行时检查并缩小类型范围。
  • 映射类型:基于旧类型创建新类型。
  • 条件类型:根据条件生成不同的类型。

通过掌握这些高级类型特性,你可以更加灵活和精确地描述代码中的数据结构和行为。

参考

标签