typescript 类型联动和互斥类型

411 阅读2分钟

交叉类型

A&B 须同时满足A和B两个类型

type struct1 = {
  primitive: string,
  object: {
    name: string
  }
}

type struct2 = {
  primitive: number,
  object: {
    age: number
  }
}

type compose = struct1 & struct2

type primitiveType = compose['primitive'] // never 因为不存在string&number类型
type objectType = compose['object'] // {name:string, age:number}

联合类型

A | B 含有A或B所有必须属性的类型

type A = {
  id: number,
  name: string
}
type B = {
  id: number,
  age: number
}
type C = A | B  // 在C内部只能访问id, 两种类型包含的唯一属性
const hand = (param: C) => {
  return param.name //报错 param.age 报错
  return param.id
}

类型联动

在一个对象中,一个属性值发生变化,会引起另一个属性的变化

通过keyof等操作生成Union类型,实现类型间的联动
type Component = {
  type: 'button' | 'input' | 'select';
  payload: {
    onChange: Function;
    onClick: Function;
    type: string;
  }
}
当type值变化时,payload类型跟着变化
// 定义类型映射关系
type ComponentPayload = {
  button: {
    onClick: Function;
    type: string
  }
  input: {
    onChange: Function
  }
  select: {
    onChange: Function
  }
}

//获取所有key
type ComponentPayloadKeys = keyof ComponentPayload; // => 'button' | 'input' | 'select'

//结合类型推导,构造valueof
type ComponentPayloadValues = ComponentPayload[keyof ComponentPayload]
// => {onClick:Function;type:string} | {onChange:Function} | {onChange:Function}

//构造出{type => {type, payload}}的格式,获取目标类型
type Component = {
  [T in keyof ComponentPayload]: {
    type: T;
    payload: ComponentPayload[T]
  }
}[keyof ComponentPayload]
//=> {type: 'button', payload: {onClick: Function, type: string}} | {type: 'input', payload: {onChange:Function}} | {type: 'select', payload: {onChange:string}}

类型互斥

一个对象中,有属性A和B,在赋值时这两个属性只能出现一个

  • 从A对象类型中剔除B对象类型的属性,将排除后的属性类型设为never,得到一个新的排除类型
  • 将A、B对象类型放入排除类型中,实现互斥
// 用keyof取出T、U的键值,使用Exclude将U从T中删除,限定K的取值范围为T的所有键,将其类型设为never
type without<T, U> = { [K in Exclude<keyof T, keyof U>]?: never }

// 互相剔除时,被剔除方必须存在
type XOR<T, U> = (without<T,U> & U) | (without<U,T> & T)