仅在类型中定义了确切属性的常量中声明的对象

时间:2019-04-10 12:50:55

标签: javascript typescript typescript-typings jsdoc

我们在基于JS的应用程序中将typescript与JSDoc一起使用,只是为了定义我们在函数中使用的参数类型。 在特定情况下,我们希望对象具有定义的结构,并且需要确保在特定类型下声明的每个对象仅具有预期的属性

type Keys = 'foo' | 'bar';

type Things = {
  [K in Keys]: Thing;
}

interface Thing {
  a: string;
  b: string;
}

在创建类型为Things的对象时,我希望它仅具有Thing中定义的属性

const object = /** @type {Things} */ ({
  foo: { a: 'foo_a', b: 'foo_b' },
  bar: { a: 'bar_a', b: 'bar_b' }
})

但是实际上,我们可以声明一个属性abc,而Typescript不会提出任何抱怨。只有在尝试访问该对象的属性时,如果我们调用类型声明中不存在的属性,它就会抱怨。例如,如果我们做object.abc,它将抱怨。

错误

如您所想,这将触发错误:

object.abc // abc is not defined in type Things

没有错误

添加类型中未定义的abc不会触发TS错误:

const object = /** @type {Things} */ ({
  foo: { a: 'foo_a', b: 'foo_b' },
  bar: { a: 'bar_a', b: 'bar_b' },
  abc: { a: 'abc_a', b: 'abc_b' },
})

在创建类型Things的对象时,我想防止在类型属性中声明未定义。

游乐场

TypeScript playground example

有人遇到任何类似的问题吗?

谢谢

1 个答案:

答案 0 :(得分:0)

如@ExplosionPills所述:

const object = /** @type {Things} */ ({
    foo: { a: 'foo_a', b: 'foo_b' },
    bar: { a: 'bar_a', b: 'bar_b' },
    abc: { a: 'abc_a', b: 'abc_b' } // This shouldn't be allowed. Not defined in Keys 
})

“对象”没有定义为“事物”类型,因此它不会出错,因为对象隐式为任何类型,因此您可以为它分配任何内容。

您需要将代码更改为:

const object : Things = /** @type {Things} */ ({
    foo: { a: 'foo_a', b: 'foo_b' },
    bar: { a: 'bar_a', b: 'bar_b' },
    abc: { a: 'abc_a', b: 'abc_b' } // This will now be highlighted as an error 
})

只有这样做,才可以将事物类型的对象分配给对象。进行更改后,您将看到Typescript抱怨该错误。