所以,我有一个(非常非常)大的对象,我希望有一个函数可以接收任何对象(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(和打字稿)知道对象的样子。我已经有了一个资源类型。可能有一个完全不同于我从这里开始的方法,我只是不确定如何开始输入它。
答案 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
是什么,我就无法轻松完成)。希望有所帮助;祝你好运!