打字稿,界面,类型,多个可选属性,以其他属性为条件的属性

时间:2018-01-28 19:33:20

标签: typescript types interface

如果属性updatedAt存在,我需要一个需要属性updatedBy的接口或类型(反之亦然);但是,它应该允许不设置任何属性。

interface BaseRow {
    id: string
    createdAt: string
    createdBy: string
}

interface Updated {
    updatedAt: string
    updatedBy: string
}

interface UpdatedRow extends BaseRow, Updated {}

type Row = BaseRow | UpdatedRow

基于以上所述,我希望以下内容会导致typescript编译器抛出错误,因为updatedAt存在但updatedBy不存在。

const x: Row = {
    id: 'someID',
    createdAt: 'someISO',
    createdBy: 'someID',
    updatedAt: 'someISO'
}

然而,上述内容并未引发任何错误。

为什么上述解决方案不能按预期工作?实现有条件地需要两个或更多属性的interfacetype的最佳方法是什么?

Typescript Playground

1 个答案:

答案 0 :(得分:2)

根据对对象literals实施严格检查的PR,执行的检查是:

  

...对象文字指定目标类型中不存在的属性

是错误的

虽然属性位于union类型的不同分支上,但属性存在于union类型上。由于其他更新的属性不存在,因此对象文字不符合UpdatedRow接口,但它确实符合Row接口,因此可以赋值给变量。这就是没有错误的原因。

在您的情况下可能适用或不适用的解决方案是通过在两个接口上添加键入不同字符串文字类型的字符串属性来确保更新的行与非更新的行不兼容:

interface BaseRow {
    id: string
    createdAt: string
    createdBy: string
}

interface Updated {
    type: 'u'
    updatedAt: string
    updatedBy: string
}

interface UpdatedRow extends BaseRow, Updated {}

type Row = (BaseRow & { type: 'n'})  | UpdatedRow

const x: Row = { // Error, no updatedBy
    type: 'u',
    id: 'someID',
    createdAt: 'someISO',
    createdBy: 'someID',
    updatedAt: 'someISO'
}

const x2: Row = { // Error, with updatedAt is not assignable to (BaseRow & { type: 'n'}) 
    type: 'n',
    id: 'someID',
    createdAt: 'someISO',
    createdBy: 'someID',
    updatedAt: 'someISO'
}