如何从ItemMetadata数组推导参数对象的TypeScript泛型类型
从const元组生成键值映射的TypeScript类型方案
基础定义
先定义元组项的类型:
type ItemMetadata = { name: string; valueType: "string" | "number" | "boolean"; };
已构造带const断言的只读元组:
const MyMetaDatas = [ { name: "The String", valueType: "string" }, { name: "The Number", valueType: "number" } ] as const satisfies readonly ItemMetadata[];
需求
需要基于上述元组生成如下结构的对象:
const MyParameters = { "The String": "string", "The Number": "number" }
同时定义泛型类型ParametersFor<T extends readonly ItemMetadata[]>,以typeof MyMetaDatas为参数,约束该对象的类型。
尝试过程
尝试1:键正确但值为所有类型的联合
最初的尝试能正确生成键,但每个值的类型会变成所有valueType的联合:
type ItemParameters<T extends readonly ItemMetadata[]> = { [K in T[number]["name"]]: T[number]["valueType"]; }; type MyParams = ItemParameters<typeof MyMetaDatas>; // 实际类型:{ "The String": "string" | "number" | "boolean"; "The Number": "string" | "number" | "boolean"; }
不符合每个键对应自身valueType的需求。
尝试2:生成单键对象元组,需合并
调整后得到能生成单键对象的元组类型,但需要将这些对象合并为一个:
type ParamsUsingSingle<T extends readonly ItemMetadata[]> = { [K in keyof T]: { [TName in T[K]["name"]]: T[K]["valueType"]; } }; type MyParamsUsingSingle = ParamsUsingSingle<typeof MyMetaDatas>; // 类型为:[{ "The String": "string" }, { "The Number": "number" }]
解决方案
正确的泛型类型定义
利用TypeScript的映射类型重命名(as子句),可以直接将元组中的每个项映射为对象的键值对,确保键与对应值类型一一对应:
type ParametersFor<T extends readonly ItemMetadata[]> = { [Item in T[number] as Item["name"]]: Item["valueType"]; };
验证类型:
type MyParams = ParametersFor<typeof MyMetaDatas>; // 正确类型:{ "The String": "string"; "The Number": "number"; }
生成符合类型约束的对象
使用数组reduce方法结合类型断言,生成符合类型的对象:
const MyParameters = MyMetaDatas.reduce((acc, item) => { acc[item.name] = item.valueType; return acc; }, {} as ParametersFor<typeof MyMetaDatas>);
内容的提问来源于stack exchange,提问作者Wish
相关产品推荐
相关产品推荐

