如何用TypeScript基于对象键动态生成Valid类型?
问题描述
我有如下动态数据:
const data = {games:{type: [], sport: [], category: []}}
当前我硬编码了类型:
type Valid = "type" & "sport" & "category"
请问如何基于Object.keys(data.games)动态生成type Valid,而非硬编码?
我尝试了以下写法:
type Valid = typeof Object.keys(data.games).join(' & ');
但出现错误:
Unexpected token, expected ";"
请帮助我实现type Valid的动态值生成。
解决方案
你之前的写法错误在于混淆了运行时代码和类型系统代码:
Object.keys()是运行时方法,TypeScript无法识别它返回的具体键名,只会将其类型判定为string[],无法直接用来构建精准类型。join(' & ')是运行时字符串拼接操作,类型系统无法将其解析为有效的交叉类型语法。
正确的做法是利用TypeScript的keyof操作符和typeof类型查询,直接从数据的静态类型中提取键名:
const data = {games:{type: [], sport: [], category: []}}; // 提取data.games的键名联合类型 type ValidUnion = keyof typeof data.games; // 此时ValidUnion的类型为 "type" | "sport" | "category" // 如果确实需要交叉类型(而非联合类型),可以通过工具类型转换: type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; type Valid = UnionToIntersection<ValidUnion>; // 此时Valid的类型为 "type" & "sport" & "category"
说明
typeof data.games会获取data.games的静态类型:{ type: never[]; sport: never[]; category: never[]; }。keyof操作符会提取该类型的所有键名,得到对应的联合类型。- 多数业务场景中,联合类型(
|)已经能满足需求;如果必须使用交叉类型(&),再通过UnionToIntersection工具类型完成转换。
内容的提问来源于stack exchange,提问作者Hello World
相关产品推荐
相关产品推荐

