【问题标题】:Creating a mapped type from an object without errors in TypeScript在 TypeScript 中从没有错误的对象创建映射类型
【发布时间】:2017-09-26 06:16:21
【问题描述】:

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

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 中无法在没有中间结果的情况下创建映射对象,您如何创建完全映射的类型?

【问题讨论】:

  • 很遗憾,这不受支持。

标签: typescript mapped-types


【解决方案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 成员 public 以显示用法!这不是必需的或任何东西。您也不必创建StatsMap,但我发现与多次写入{ [K in keyof T]: Stats } 相比,它更易于阅读。

【讨论】:

    猜你喜欢
    • 2018-04-04
    • 2018-10-08
    • 2023-04-10
    • 2020-02-19
    • 1970-01-01
    • 2018-05-06
    • 2021-03-28
    • 1970-01-01
    • 2020-11-25
    相关资源
    最近更新 更多