键入静态对象的值,同时保留其键类型

时间:2021-05-21 17:41:41

标签: typescript

假设我有以下接口和对象:

interface Person {
  name: string;
  lastName?: string;
}

const obj: { [key: string]: Person } = {
  a: { name: 'John' },
  b: { name: 'Jane', lastName: 'Doe' },
}

这定义了对象的类型,使其键可以是任何 string。但是我希望仍然能够推断出对象的键(因为它是静态的),在这种情况下,我不能。

我可以这样做:

type ObjKeys = 'a' | 'b';

const obj: { [key in ObjKeys]: Person } //...

但它很冗长。

是否有一种简短的方式说“这里是这个对象的所有值的类型,但保留静态定义的键?”

1 个答案:

答案 0 :(得分:1)

你不能纯粹在类型级别这样做;如果您使用 obj annotate {[k: string]: Person} 的类型,那么编译器将假定这是要使用的实际类型,并且不会根据分配将其 narrow 为其他类型{a: {...}, b: {...}}。此类 control flow analysis 仅适用于类型为 union{[k: string]: Person} 不是联合的值。

在这种情况下,我通常做的是编写一个 generic 助手 identity function,编译器可以从中推断出您正在寻找的类型:

const asPersonDict = <K extends PropertyKey>(
  o: { [P in K]: Person }) => o;

然后你调用辅助函数而不是注释类型:

const obj = asPersonDict({
  a: { name: 'John' },
  b: { name: 'Jane', lastName: 'Doe' },
});

/* const obj: {
    a: Person;
    b: Person;
} */

Playground link to code