在 Typescript 中键入键值对对象并保存对象的键

时间:2021-02-23 04:06:56

标签: typescript

我在下面的例子中有键值对对象

preg_split('/(<|>)/m', $xmlString);

但它会引发错误,例如 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,我将丢失列表的键名。 :(

1 个答案:

答案 0 :(得分:7)

如果您想验证一个值是否可分配给某个类型,而不将其扩展到该类型,并且可能会丢弃您关心的信息,则可以使用辅助标识函数,如下所示:

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},根据需要。

Playground link to code

相关问题