TypeScript的高级类型

TypeScript的高级类型

2022-10-18
前端TypeScript
AI 智能概括

TypeScript 的高级类型系统提供了强大的能力,使得开发者能够更精确地控制类型,提高代码的可读性和可维护性。联合类型允许变量可以是多种类型之一,交叉类型合并多个类型,映射类型根据现有类型创建新类型,条件类型根据类型判断选择不同的类型,索引类型通过索引访问对象属性并推断类型,类型别名简化复杂类型定义,类型约束限制泛型类型参数的范围。这些高级类型系统使得 TypeScript 成为一种更加灵活和安全的编程语言

Powered by DeepSeek

1. 联合类型(Union Types)

联合类型用 | 符号表示,表示一个变量可以是多种类型之一。这在参数或返回值可以是多种类型的情况下非常有用。

typescript
function formatInput(input: string | number): string {
  return String(input);
}

上述例子中的 formatInput 函数接受一个参数 input,它可以是 string 类型或 number 类型。使用联合类型,函数内部可以安全地将输入转换为字符串,因为无论输入是字符串还是数字,最终都会得到正确的输出。

2. 交叉类型(Intersection Types)

交叉类型用 & 符号表示,表示一个新类型包含多个原始类型的所有属性。

typescript
interface A {
  foo: number;
}
 
interface B {
  bar: string;
}
 
type C = A & B;
 
const obj: C = { foo: 42, bar: "Hello" };

在上面的例子中,我们定义了接口 AB,分别拥有 foobar 属性。然后我们使用交叉类型 CAB 合并成一个新类型,即 C 包含了 AB 的所有属性。最后,我们创建一个对象 obj,它满足 C 类型,即同时包含 foobar 属性。

3. 映射类型(Mapped Types)

映射类型可以用来从一个已有的类型创建一个新的类型,通过对原类型的属性进行修改或添加。

typescript
interface Person {
  name: string;
  age: number;
}
 
type ReadonlyPerson = Readonly<Person>;
// 等价于
// type ReadonlyPerson = {
//   readonly name: string;
//   readonly age: number;
// };

上述例子中,我们使用 Readonly<Person> 来创建一个新类型 ReadonlyPerson,它是 Person 的只读版本,所有属性都被设为只读。

4. 条件类型(Conditional Types)

条件类型用于根据类型判断来选择不同的类型。通过 extends 关键字和三元运算符 ?: 来实现。

typescript
type MyType<T> = T extends number ? string : boolean;
 
let result1: MyType<number> = "hello"; // Error: 类型“string”的参数不能赋给类型“boolean”的参数
let result2: MyType<number> = true;   // Error: 类型“boolean”的参数不能赋给类型“string”的参数
let result3: MyType<number> = false;  // OK

在上面的例子中,我们定义了一个条件类型 MyType<T>,如果类型 Tnumber,则返回 string 类型,否则返回 boolean 类型。根据 result1result2result3 的赋值情况可以看到,条件类型根据不同的类型参数返回了不同的结果类型。

5. 索引类型(Index Types)

索引类型用于通过索引访问对象的属性,并根据索引的类型推断出对应属性的值的类型。

typescript
interface Person {
  name: string;
  age: number;
}
 
type PersonKeys = keyof Person; // "name" | "age"
 
let key: PersonKeys = "name";
let person: Person = { name: "Alice", age: 30 };
let value: Person[typeof key]; // string

上述例子中,keyof Person 获得了 Person 类型的所有属性名,然后通过 Person[typeof key] 推断出 person 对象中 key 属性的值的类型。

6. 类型别名(Type Alias)

类型别名用于为一个类型定义一个别名,可以将复杂类型命名为更简洁的名称,提高代码可读性和可维护性。

typescript
type Point = {
  x: number;
  y: number;
};
 
let p: Point = { x: 1, y: 2 };

在上面的例子中,我们使用 type 关键字定义了一个类型别名 Point,表示一个拥有 xy 属性的对象。通过类型别名,我们可以在代码中使用 Point 来表示这种类型的对象,使得代码更加清晰。

7. 类型约束(Type Constraint)

类型约束用于限制泛型类型参数的范围,使得泛型只能接受符合特定条件的类型。

typescript
function printLength<T extends { length: number }>(arg: T): void {
  console.log(arg.length);
}

在上面的例子中,我们定义了一个泛型函数 printLength,使用 extends 关键字对类型参数 T 进行约束,要求 T 必须包含一个 length 属性,且该属性的类型必须是 number。这样,我们可以在函数内部安全地访问 arg.length 属性。

typescript
printLength("Hello"); // 输出:5
printLength([1, 2, 3, 4, 5]); // 输出:5
printLength({ length: 10 }); // 输出:10

需要注意的是,类型约束使得泛型更具有通用性和类型安全性,可以适用于更多的场景。

总结归纳

TypeScript 中的高级类型包括:

  1. 联合类型(Union Types):表示一个变量可以是多种类型之一。
  2. 交叉类型(Intersection Types):合并多个类型,包含所有类型的特性。
  3. 映射类型(Mapped Types):从一个现有的类型创建新的类型,通过对原类型的属性进行修改或添加。
  4. 条件类型(Conditional Types):根据类型判断选择不同的类型。
  5. 索引类型(Index Types):通过索引访问对象属性,并根据索引的类型推断出对应属性的值的类型。
  6. 类型别名(Type Alias):为类型定义一个别名,提高代码可读性和可维护性。
  7. 类型约束(Type Constraint):限制泛型类型参数的范围,使得泛型只能接受符合特定条件的类型。
发布于 2022-10-18