TypeScript 高级类型 - 可辨识联合

首先先来描述一个需求场景,例若有一个建立用户和更新用户的功能,其中要传给服务端的字段除了「更新」须要多一个「id」属性之外其他属性都同样。typescript

在此我先定义一个接口来声明这个参数对象的类型:函数

interface Prop{
    action:'create'|'update';
    id?:string;
    name:string;
}
复制代码

可是咱们发现,这个接口并不知足咱们的需求,由于咱们这样建立对象依然会经过:ui

const a:Prop = {
    action:'create',
    id:'1',
    name:'zhangsan'
}
复制代码

这个类型并不会经过 action 的值来帮我判断是否应该有 id 字段。spa

接下来换个写法来改进一下:code

type Prop =
  | {
      action: "create";
      name: string;
    }
  | {
      action: "update";
      id: string;
      name: string;
    };

const a: Prop = {
  action: "update",
  name: "zhangsan"
};
复制代码

这时若是咱们声明一个 Prop 类型的变量没有 id 属性,TypeScript 就会报出异常:对象

Property 'id' is missing in type '{ action: "update"; name: string; }' but required in type '{ action: "update"; id: string; name: string; }'.接口

这就顺利解决了咱们的问题,可是接着又遇到一个问题,当我在一个函数中传入 Prop 类型的参数,并使用了它的 id 属性时,TypeScript 又报了一个错误:ip

type Prop =
  | {
      action: "create";
      name: string;
    }
  | {
      action: "update";
      id: string;
      name: string;
    };

function fn(e: Prop) {
  console.log(e.id);
}
// Property 'id' does not exist on type '{ action: "create"; name: string; }'.
复制代码

原来是 TypeScript 并不肯定你传进来的对象的 actionupdate 仍是 create,因此继续改进一些代码来帮助 TypeScript 判断:string

type Prop =
  | {
      action: "create";
      name: string;
    }
  | {
      action: "update";
      id: string;
      name: string;
    };

function fn(e: Prop) {
  if (e.action === "create") {
    console.log(e.name);
  } else {
    console.log(e.id);
  }
}
复制代码

这样报错就顺利解决了。it

咱们一直在使用的 type Prop 这个类型就是一个可辨识联合,从上面的代码来看它有如下特色:

  1. 一个共有的字段。在上文中这个共有字段是 action
  2. 这个共有字段的值是可穷举的。由于若是值是不可穷举的,就没法用选择语句来对变量的具体类型进行判断。
相关文章
相关标签/搜索