英文:
Typescript extract keys from an object where each key value has a specific property
问题
type GeneratedStatKeys = {
[I in keyof typeof STATS]: typeof STATS[I]['generated'] extends undefined ? never : I;
}; // "minpg" | "avgrec"
英文:
I have a read-only object that is used to represent the stats for my game like so:
const STATS = {
gp: {
name: "Games Played",
slug: "GP",
},
minp: {
name: "Minutes Played",
slug: "MINP",
},
minpg: {
name: "Average Minutes Per Game",
slug: "MINPG",
generated: {
// ...properties,
},
},
avgrec: {
name: "Average Receptions",
slug: "avgrec",
generated: {
// ...properties,
},
},
} as const;
I want to extract all the keys from the object that have a generated property set. That way I can use this key in some of my utility functions. Thus, I tried the below:
type GeneratedStatKeys = {
[I in keyof typeof STATS]: typeof STATS[I]["generated"] extends undefined
? never
: typeof STATS[I];
}; // "minpg" | "avgrec"
GeneratedStatKeys should be a union type of strings, the extracted keys of STATS. However, Typescript is throwing an error "Type '"generated"' cannot be used to index type STATS"
This makes sense, so I annotated the STATS object to be:
const STATS: Record<string, Stat> = {
//...stats
} as const;
where Stat is:
interface Stat {
name: string;
slug: string;
generated?: {
//...props
};
}
This works, however, GeneratedStatKeys type is then string.
What is the workaround? I could just manually create a string union type for the generated keys but was wondering if this could be "automated".
答案1
得分: 2
无法使用类型的键索引,除非它是类型的已知键。由于typeof STATS
的某些属性没有generated
键,因此无法以这种方式对任意属性进行索引。相反,您可以使用keyof运算符来检查属性是否具有该键:
type GeneratedStatKeys = {
[K in keyof typeof STATS]: "generated" extends keyof typeof STATS[K] ? K : never
}[keyof typeof STATS]
// type GeneratedStatKeys = "avgrec" | "minpg"
一旦进行了这个检查,您就可以进行索引访问(例如,"generated" extends keyof Foo ? Foo[K] : ...
),但在您的情况下,您只需要键,而不是属性类型。
英文:
You can't index into a type with a key unless it's a known key of the type. Since some of the properties of typeof STATS
don't have a generated
key, you can't index into an arbitrary property that way. Instead you could check if the property has that key by using the keyof
operator:
type GeneratedStatKeys = {
[K in keyof typeof STATS]: "generated" extends keyof typeof STATS[K] ? K : never
}[keyof typeof STATS]
// type GeneratedStatKeys = "avgrec" | "minpg"
Once you did this check you could do the indexed access (e.g., "generated" extends keyof Foo ? Foo[K] : ...
) but in your case you just want the key, not the property type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论