跳至主要內容

高级类型


高级类型

交叉类型(&且)

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

interface PointX {
  x: number
}

interface PointY {
  y: number
}

interface 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: () => any
  layEggs: () => any
}

interface Fish {
  swim: () => any
  layEggs: () => any
}

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

const pet = getSmallPet()

// 正常使用
pet.layEggs()

// 出现错误
pet.swim()

类型区分

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

interface Bird {
  fly: () => any

  layEggs: () => any
}

interface Fish {
  swim: () => any

  layEggs: () => any
}

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

const 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
const 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>>