You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建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();

原理说明

  1. 遍历元素联合类型:Args[number]会提取数组中所有元素的联合类型(当数组用const断言时,每个元素的name和multiple都是字面量类型)。
  2. 键重映射:通过as ExtractName<T>将每个元素的name属性作为对象的键。
  3. 类型推导:ExtractValue<T>会根据每个元素的multiple字面量值,精确推导对应的值类型(string[]或string)。

原写法的问题在于keyof Args包含数组的所有键(如length、slice等),这些键对应的Args[N]不是ArgumentSpec类型,导致ExtractName报错;同时遍历索引无法正确保留元素的字面量类型。

内容的提问来源于stack exchange,提问作者Frando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:30:49