类型脚本:定义一个接口/类型,其中至少存在两个属性之一(也可以同时存在)

时间:2019-12-23 21:24:44

标签: typescript

我想描述以下界面

interface IDamageDetailsBase {
    id: string;
    referenceId: string;
    imageId: string;
}

要注意的是,在上述对象中,以下组合是可能的

  • id和referenceId,都可以存在
  • 只能显示ID
  • 如果没有id,则将存在referenceId
  • id和referenceId都不存在

我尝试了以下

interface IDamageDetailsBase {
  imageId: string;
}

type IDamageDetails = (
  | { id: string }
  | { referenceId: string }
  | { referenceId: string; id: string }) &
  IDamageDetailsBase;

const getId = (damageDetail: IDamageDetails) => damageDetail.id || damageDetail.referenceId

这给了我以下错误

Property 'id' does not exist on type 'IDamageDetails'.
  Property 'id' does not exist on type '{ referenceId: string; } & IDamageDetailsBase'.
Property 'referenceId' does not exist on type 'IDamageDetails'.
  Property 'referenceId' does not exist on type '{ id: string; } & IDamageDetailsBase'.

有人可以向我解释如何建模吗?

1 个答案:

答案 0 :(得分:0)

编辑:

无需更改类型,您也可以只使用in type guard

// getId: (damageDetail: IDamageDetails) => string
const getId = (damageDetail: IDamageDetails) =>
    "id" in damageDetail ? damageDetail.id : damageDetail.referenceId

Sample Code


原始答案:

您会收到错误消息,因为仅可以访问联合类型中的公共属性,而无需将类型进一步缩小。

referenceId在第一联合部分中不存在,并且第二联合组成部分不包含id。因此,第一步是添加undefined类型的缺少的常见道具:

type IDamageDetails = (
    | { id: string; referenceId: undefined }
    | { id: undefined; referenceId: string }
    | { id: string; referenceId: string }) &
    IDamageDetailsBase;

nullish coalescing operator的帮助下,您现在将始终获得string的回馈:

// getId: (damageDetail: IDamageDetails) => string
const getId = (damageDetail: IDamageDetails) => damageDetail.id ?? damageDetail.referenceId

之所以可行,是因为IDamageDetailsdiscriminated union typeid: undefinedreferenceId: undefined的{​​{3}}。它们包含一个单例undefined类型,该类型恰好存在于三个联合案例之一。因此,编译器将知道,给定一个为undefined,另一个为string

discriminant properties