我在下面的例子中有键值对对象
interface ItemType {
a: number;
b: string;
}
const list = {
first: {a: 1, b: 'one'},
second: {a: 2, b: 'two'},
third: {a: 3, b: 'three'},
} as { [key in keyof typeof list]: ItemType }
但它会引发错误,例如 TS2313: Type parameter 'key' has a circular constraint.
。
我希望所有项目都是 ItemType
类型,但仍希望列表保存我插入的键。如果我将它转换为 { [key in string]: ItemType }
,我将丢失列表的键名。 :(
最佳答案
如果您想验证某个值是否可分配给某个类型而不扩大到该类型并可能丢弃您关心的信息,您可以使用辅助标识函数,如下所示:
const itemDict = <K extends PropertyKey>(dict: { [P in K]: ItemType }) => dict;
这里 itemDict()
应该只接受一个你正在寻找的类型的对象作为参数:它的键是任何类似键的 K extends PropertyKey
这将调用时由编译器推断,其属性为 ItemType
。因为键集 K
是类型的一部分,所以不会被遗忘:
const list = itemDict({
first: { a: 1, b: 'one' },
second: { a: 2, b: 'two' },
third: { a: 3, b: 'three' },
});
list.second.a.toFixed(); // okay
list.fourth; // error!
// Property 'fourth' does not exist on type
// '{ first: ItemType; second: ItemType; third: ItemType; }'
请注意,list
由编译器根据需要推断为类型 {first: ItemType, second: ItemType, third: ItemType}
。
关于typescript - 在 Typescript 中键入键值对对象并保存对象的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66326903/