对于返回作为原始对象子集的对象的函数,类型定义会是什么样子 [英] What would the type definition look like for a function that returns an object that is a subset of an original object
问题描述
所以,我有一个(非常非常)大的对象,我想要一个函数,它接受任何对象 (T) 及其键列表(K 扩展 keyof T)并返回一个新对象只有那些传入的键/值.本质上是 {[key: K]: string}.
So, I've got a (very, very) large object, and I want to have a function that takes in any object (T) and a list of its keys (K extends keyof T) and returns a new object with only those keys/values that were passed in. Essentially {[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' 下失败.
I have been trying to write the type definition for this function, but it fails under 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(和打字稿)根据传入的内容知道该对象的外观.我已经有了一个资源类型.可能有一种与我在这里开始的方法完全不同的方法,我只是不知道如何开始输入这个.
My goal here is to get that subset object, and have my IDE (and typescript) know what the object looks like based on what was passed in. I already have a type for resources. There may be a wholly different approach than how I've started here, I'm just not sure how else to even start typing this.
推荐答案
你已经很接近了;您正在寻找 映射类型,它允许您迭代键(而不是使用索引器).也就是说,不要使用这个:
You're pretty close; you're looking for mapped types which allow you to iterate over keys (as opposed to using an indexer). That is, don't use this:
{[key: K]: IResources[K]}
改用这个:
{[P in K]: IResources[P]}
事实上,这是一个足够有用的结构,它存在于 标准库 as Pick
:
In fact, this is a useful enough construct that it exists in the standard library as Pick<T,K>
:
Pick<IResources, K>
所以你的函数变成了这样:
So your function becomes something like:
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]
}), {});
}
这将无法在实现中进行类型检查,因为我认为 TypeScript 不理解 Pick
上的传播类型.如果您确定实现中的一切都很好,您可以使用 any
断言来帮助:
This will fail to type check in the implementation because I don't think TypeScript understands the spread type on Pick<IResources, K>
. If you're sure everything in the implementation is fine, you can use an any
assertions to help:
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
是什么,我无法轻松做到).希望有所帮助;祝你好运!
You can verify that this behaves as desired (I can't easily do it without knowing what IResources
is). Hope that helps; good luck!
这篇关于对于返回作为原始对象子集的对象的函数,类型定义会是什么样子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!