【TypeScript】高级类型

2021/09/09 09:35:32

摘要

  1. 使用 & 将多个类型合并为新的交叉类型,新类型同时拥有了其他类型的成员。
  2. 使用 | 表示联合类型,如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。
  3. 类型谓词关键字:is
  4. 添加 ! 后缀表示断定确实已赋值。
  5. type 关键字设置类型别名,起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型。
  6. 字符串字面量类型允许你指定字符串必须的固定值,数字字面量类型同理。

交叉类型

交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含合并的所有类型的特性,就是说新类型同时拥有了其他类型的成员。

使用 & 将多个类型合并为新的交叉类型。

联合类型

使用 | 表示联合类型,number | string | boolean表示一个值可以是 numberstring,或 boolean

如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。

类型保护

类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。

  • 类型谓词 is 实现类型保护

要定义一个类型保护,我们只要简单地定义一个函数,它的返回值是一个 类型谓词

function isFish(pet: Fish | Bird): pet is Fish {
    return (<Fish>pet).swim !== undefined;
}

去除 null 和 undefined

使用类型断言手动去除 nullundefined,语法是添加 ! 后缀: identifier!identifier 的类型里去除了 nullundefined

添加 ! 后缀表示断定确实已赋值。

类型别名

给类型起一个新名字,可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。

起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型。

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
  if (typeof n === "string") {
    return n;
  } else {
    return n();
  }
}
getName(() => "");
getName("");
  • 泛型类型别名
type Container<T> = { value: T };
  • 在类型别名中引用自己
type Tree<T> = {
  value: T,
  left: Tree<T>,
  right: Tree<T>,
};

字面量类型

  • 字符串字面量类型 字符串字面量类型允许你指定字符串必须的固定值。
type Easing = "ease-in" | "ease-out" | "ease-in-out";
  • 数字字面量类型
type Easing = 1 | 2 | 3;

可辨识联合

  • 可辨识联合具有一下特征
  1. 具有相同类型属性作为各自的特征以区分具体类型,在下例中为 kind 属性。
  2. 一个包含了那些类型联合的类型别名— 联合,在下例中为 Shape 类型。
  3. 此属性上的类型保护。
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(s: Shape) {
  switch (s.kind) {
    case "square":
      return s.size * s.size;
    case "rectangle":
      return s.height * s.width;
    case "circle":
      return Math.PI * s.radius ** 2;
  }
}

索引类型

使用索引类型,编译器就能够检查使用了动态属性名的代码。

function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
  return names.map(n => o[n]);
}

interface Person {
    name: string;
    age: number;
}
let person: Person = {
    name: 'Jarid',
    age: 35
};
let strings: string[] = pluck(person, ['name']); // ok, string[]
  1. 索引类型查询操作符 keyof,在这里 keyof T 等价于 'name' | 'age'
  2. 索引访问操作符 T[K],在这里表示 person['name'] 具有 Person['name'] 类型——在上例中则是 string 类型。