1

如何从对象创建映射类型?如果我尝试以下操作:

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; }'

这似乎是因为 is 中的初始值reduce与接口不匹配。

我可以将我的声明更改为一种解决方法:

private stats: { [K in keyof T]?: Stats };

...但是现在这意味着 keyof T 的某些值可能根据类型未定义。

鉴于无法在 JavaScript 中创建没有中间结果的映射对象,您如何创建一个完全映射的类型?

4

1 回答 1

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 你知道你在做什么:- /

您可以在操场上进行测试

请注意,我制作了stats成员public以显示用法!这不是必需的或任何东西。您也不必创建,但与多次StatsMap编写相比,我发现它更容易阅读。{ [K in keyof T]: Stats }

于 2017-04-28T08:44:49.380 回答