对于返回作为原始对象子集的对象的函数,类型定义是什么样的

时间:2018-03-04 03:00:59

标签: typescript typescript-typings

所以,我有一个(非常非常)大的对象,我希望有一个函数可以接收任何对象(T)和它的键列表(K扩展keyof T)并返回一个新对象只有那些传入的键/值。基本上{[key:K]:string}。

以下是有问题的功能:

export function mapResources(resources, keys: string[]) {
  return keys.reduce((response, key) => ({
      ...response,
      [key]: resources[key]
  }), {});
}

我一直在尝试为此函数编写类型定义,但它在TS1023: An index signature parameter type must be 'string' or 'number'.

下失败
export function mapResources<K extends keyof IResources>(resources: IResources, keys: K[]): {[key: K]: IResources[K]} {
  return keys.reduce((response, key) => ({
      ...response,
      [key as string]: resources[key]
  }), {});
}

我的目标是获取该子集对象,并根据传入的内容让我的IDE(和打字稿)知道对象的样子。我已经有了一个资源类型。可能有一个完全不同于我从这里开始的方法,我只是不确定如何开始输入它。

1 个答案:

答案 0 :(得分:3)

你很亲密;你正在寻找允许你迭代键的mapped types(而不是使用索引器)。也就是说,不要使用它:

{[key: K]: IResources[K]}

改为使用:

{[P in K]: IResources[P]}

事实上,这是一个非常有用的构造,它在standard library中作为Pick<T,K>存在:

Pick<IResources, K>

所以你的功能就像:

export function mapResources<K extends keyof IResources>(resources: IResources, keys: K[]): Pick<IResources, K> {
  return keys.reduce((response, key) => ({
      ...response,
      [key as string]: resources[key]
  }), {});
}

这将无法在实现中键入check,因为我认为TypeScript不会理解Pick<IResources, K>上的传播类型。如果你确定实现中的所有内容都很好,你可以使用any断言来帮助:

export function mapResources<K extends keyof IResources>(resources: IResources, keys: K[]): Pick<IResources, K> {
  return keys.reduce((response, key) => ({
      ...(response as any),
      [key]: resources[key]
  }), {});
}

您可以验证此操作是否符合要求(如果不知道IResources是什么,我就无法轻松完成)。希望有所帮助;祝你好运!