跳至主要內容

高级类型

微信公众号:储凡About 8 min

高级类型

交叉类型(&且)

将多个类型叠加合并为一个类型,涵盖所有类型的特性

type PointX = {
  x: number
}

type PointY = {
  y: number
}

type PointZ = {
  z: number
}

// 同时具备多个类型的特性
type PointXYZ = PointX & PointY & PointZ
const pointXYZ: PointXYZ = {
  x: 1,
  y: 2,
  z: 3
}
console.log(pointXYZ)

联合类型(|或)

指定将多个类型联合起来,新的类型可以为多个类型的一种

type typeString = string
type typeNumber = number

type newType = typeString | typeNumber

// arg既可以是string也可以是number类型
function test(arg: newType) {
  return arg
}

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

interface Bird {
  fly();

  layEggs();
}

interface Fish {
  swim();

  layEggs();
}

function getSmallPet(): Fish | Bird {
  // ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim();    // errors

类型区分

利用类型断言,来进行类型区分,有点像指定泛型

interface Bird {
  fly();

  layEggs();
}

interface Fish {
  swim();

  layEggs();
}

function getAnimal(): Fish | Bird {
  // ...
}

let animal = getAnimal();
animal.layEggs() // okay
animal.swim()    // errors
animal.fly()     // errors

// 断言为Bird类型
if ((<Bird>animal).fly != null) {
  (<Bird>animal).fly()
}

if ((<Fish>animal).swim != null) {
  (<Fish>animal).swim()
}

类型保护

  • typeof 判断类型, 支持的类型只有四种:
    • number
    • string
    • boolean
    • symbol
  • instanceof 判断是否为某类的实例化对象
interface Padder {
  getPaddingString(): string
}

class SpaceRepeatingPadder implements Padder {
  constructor(private numSpaces: number) {
  }

  getPaddingString() {
    return Array(this.numSpaces + 1).join(" ");
  }
}

class StringPadder implements Padder {
  constructor(private value: string) {
  }

  getPaddingString() {
    return this.value;
  }
}

function getRandomPadder() {
  return Math.random() < 0.5 ?
    new SpaceRepeatingPadder(4) :
    new StringPadder("  ");
}

// 类型为SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();

if (padder instanceof SpaceRepeatingPadder) {
  padder; // 类型细化为'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
  padder; // 类型细化为'StringPadder'
}

索引类型

利用索引类型查询、索引访问处理

function pluck(o, names) {
  return names.map(n => o[n]);
}


// keyof T 索引类型查询
// K[T] 索引访问 
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
  return names.map(n => o[n]);
}


// 字符串索引类型签名
interface Map<T> {
  [key: string]: T;
}

let keys: keyof Map<number>; // string
let value: Map<number>['xxxx']; // number

映射类型

// 只读类型
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
}

// 可选类型
type Partial<T> = {
  [P in keyof T]?: T[P];
}

语法与索引签名的语法类型,内部使用了 for .. in。 具有三个部分:

  1. 类型变量 K,它会依次绑定到每个属性。
  2. 字符串字面量联合的 Keys,它包含了要迭代的属性名的集合。
  3. 属性的结果类型。

有条件类型

  • Exclude<T, U>:从T中剔除可以赋值给U的类型。
  • Extract<T, U>:提取T中可以赋值给U的类型。
  • NonNullable<T>:从T中剔除null和undefined。
  • ReturnType<T>:获取函数返回值类型。
  • InstanceType<T>:获取构造函数类型的实例类型
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">;  // "b" | "d"
type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">;  // "a" | "c"

// string | number
type T02 = Exclude<string | number | (() => void), Function>;

// () => void
type T03 = Extract<string | number | (() => void), Function>;

// string | number
type T04 = NonNullable<string | number | undefined>;

// (() => string) | string[]
type T05 = NonNullable<(() => string) | string[] | null | undefined>;

function f1(s: string) {
  return {a: 1, b: s};
}

class C {
  x = 0;
  y = 0;
}

type T10 = ReturnType<() => string>;  // string
type T11 = ReturnType<(s: string) => void>;  // void
type T12 = ReturnType<(<T>() => T)>;  // {}
type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>;  // number[]
type T14 = ReturnType<typeof f1>;  // { a: number, b: string }
type T15 = ReturnType<any>;
// anytype T16 = ReturnType<never>;  
// anytype T17 = ReturnType<string>;  
// Errortype T18 = ReturnType<Function>;  
// Errortype T20 = InstanceType<typeof C>;  
// Ctype T21 = InstanceType<any>;  
// anytype T22 = InstanceType<never>;  
// anytype T23 = InstanceType<string>;  
// Errortype T24 = InstanceType<Function>;  // Error


// 没有Omit<T,K>,可以采用等价写法
Pick<T, Exclude<keyof T, K>>