我有一个相当复杂的interface
,它有许多众所周知的示例。这些示例应该可以通过某种ID引用。理想情况下,我希望在一个对象中定义所有这些众所周知的示例,这样我就可以使用keyof
操作符来轻松地为键指定一个类型。
interface Complex {
frobs: number[];
type: 'A' | 'B';
} // More complicated in reality
const COMMON = {
foo: { type: 'A', frobs: [] }, // this is fine
bar: { type: 'B', frobs: [1], zorg: 1 }, // unwanted extra
baz: { type: 'A', noFrobs: "uh-oh" }, // frobs missing
}
Type CommonId = keyof typeof COMMON; // Great, valid Ids are "foo" | "bar" | "baz"
但是,如果我指定了没有任何类型的对象(如上所述),Typescript当然不会强制该对象中的所有值都应该是同一类型。
所以我想指定所有的值都必须是Complex
类型,但是如果不指定键类型,我就无法做到这一点,现在我必须对每个键重复一次:一次作为CommonId
的一部分,一次在对象中:
interface Complex {
frobs: number[];
type: 'A' | 'B';
} // More complicated in reality
type CommonId = "foo" | "bar"; // Much more common objects in reality
const COMMON: {
[commonId in CommonId]: Complex
} = {
foo: { type: 'A', frobs: [] },
bar: { type: 'B', frobs: [1] }
}
有没有办法两全其美呢?我希望用一个新的键-值对扩展COMMON
变量,自动将该键添加到CommonId
类型中。
3条答案
按热度按时间bxpogfeg1#
你可以先创建一个不带类型的变量,用它来获取键的类型,然后导出相同的值,但是类型如下:
Playground链接
avwztpqn2#
从Typescript 4.9开始,这可以通过
satisfies
关键字轻松完成:这是一个进一步简化的解决方案(主要归功于Aplet123,因为它受到了他的回答,特别是他的评论的启发,只有我写的一个额外的泛型函数)。我的用例实际上是定义一个配置,因此
makeConfig
的名称。如果有用的话,你可以导出并重用一个通用类型的config函数:
然后像这样简单地使用它:
(Note不需要像
CommonId
这样的其他变量/类型声明,除非您想导出它们)或者,如果您只想对Complex类型使用一次:
EDIT:或者稍微简洁一点:
总的来说,我们确实需要TS中的一个内置机制来强制值的类型,而不使用索引类型,索引类型会丢失关于键名的信息...
twh00eeo3#