如何从对象创建映射类型?如果我尝试以下内容:
interface Stats {
count: number,
avg: number
}
class Blah<T> {
private stats: { [K in keyof T]: Stats };
constructor(foo: T) {
this.stats = Object
.keys(foo)
.reduce((result, key) => Object.assign(result, {
[key]: { count: 0, avg: 1 }
}), {});
}
}
...我收到错误:
类型“{}”不能分配给类型'{[K in keyof T]:Stats; }“
这似乎是因为reduce
中的初始值与界面不匹配。
我可以将此声明更改为解决方法:
private stats: { [K in keyof T]?: Stats };
...但现在意味着keyof T的某些值可能根据类型未定义。
如果无法在JavaScript中创建没有中间结果的映射对象,如何创建完全映射的类型?
答案 0 :(得分:1)
这有点单调乏味,但您可以执行以下操作:
interface Stats {
count: number,
avg: number
}
type StatsMap<T> = { [K in keyof T]: Stats };
class Blah<T> {
public stats:StatsMap<T>;
constructor(foo: T) {
this.stats = Object
.keys(foo)
.reduce<StatsMap<T>>((result, key) => Object.assign(result, {
[key]: { count: 0, avg: 1 }
}), {} as any);
}
}
const blah = new Blah({ a: 'a', b: 'b', c: 'c' });
console.log(blah.stats.a.avg); // Yay, no error + autocomplete!
{} as any
需要告诉TypeScript您知道自己在做什么: - /
你可以test this on the playground。
请注意,我创建了stats
memboer public
来显示用法!这不是必需的或任何东西。您也不必创建StatsMap
,但与多次撰写{ [K in keyof T]: Stats }
相比,我觉得更容易阅读。