如何创建TypeScript类型将const对象数组转为const记录对象
如何将const对象数组转换为带固定键的类型化记录对象?
问题描述
需要编写一个TypeScript类型,将const断言的对象数组转换为记录对象:
- 对象的键取自数组每个元素的
name属性 - 对象的值类型根据元素的
multiple属性决定(true对应string[],false对应string) - 要求保留每个元素的具体字面量类型,而非宽泛的
ArgumentSpec类型
当前尝试的TypedArguments类型中,ExtractName<Args[N]>无法正常工作,导致无法生成预期的类型化对象。
解决方案
核心问题在于原写法遍历了数组的所有键(包括length等内置属性),且未正确提取数组元素的具体字面量类型。修改类型定义,直接遍历数组的元素联合类型即可解决:
type ExtractName<T extends ArgumentSpec> = T['name']; type ExtractValue<T extends ArgumentSpec> = T['multiple'] extends true ? string[] : string; // 关键修改:遍历数组的元素联合类型 Args[number] type TypedArguments<Args extends readonly ArgumentSpec[]> = { readonly [T in Args[number] as ExtractName<T>]: ExtractValue<T>; }; export interface ArgumentSpec { name: string; multiple: boolean; } function mapArguments<Args extends readonly ArgumentSpec[]>(args: Args): TypedArguments<Args> { return args.reduce( (agg, arg) => ({ ...agg, [arg.name]: arg.multiple ? ['foo', 'bar'] : 'baz' }), {} as any ) as TypedArguments<Args>; } // 测试代码 const mapped = mapArguments([ { name: 'key1', multiple: true }, { name: 'key2', multiple: false } ] as const); // 现在可以正常工作 mapped.key1.map((x: string) => x.toUpperCase()); mapped.key2.toUpperCase();
原理说明
- 遍历元素联合类型:
Args[number]会提取数组中所有元素的联合类型(当数组用const断言时,每个元素的name和multiple都是字面量类型)。 - 键重映射:通过
as ExtractName<T>将每个元素的name属性作为对象的键。 - 类型推导:
ExtractValue<T>会根据每个元素的multiple字面量值,精确推导对应的值类型(string[]或string)。
原写法的问题在于keyof Args包含数组的所有键(如length、slice等),这些键对应的Args[N]不是ArgumentSpec类型,导致ExtractName报错;同时遍历索引无法正确保留元素的字面量类型。
内容的提问来源于stack exchange,提问作者Frando
相关产品推荐
相关产品推荐

