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

如何利用TypeScript提取的联合类型动态初始化对象?

问题描述

我有一个只读对象数组,通过TypeScript工具类型从中提取字段得到了联合类型RawId,并基于它定义了test类型。现在想程序化地将这个类型的所有字段初始化为0——原数组可能包含数百个元素,手动初始化实在太繁琐。

相关代码如下:

const items = [
{
   id: "id1",
   type: "raw"
},
{
   id: "id2",
   type: "raw"
},
{
   id: "id3",
   type: "raw"
}
] as const

type Item = typeof items[number]

type RawId = Pick<Extract<Item, {type: 'raw'}>, 'id'>['id'];
// type RawId = "id1"|"id2"|"id3"

type test = {[key in RawId ]: number};
// type test = {
//     id1: number;
//     id2: number;
//     id3: number;
// }

我试过下面的写法,但完全不生效:

const initialValue: test = {
    // 此写法不生效
    [key in keyof typeof RawId ]: 0
}
解决方案

TypeScript的类型是编译时概念,没法直接在运行时用类型生成对象。但我们可以基于原始的items数组(运行时存在的值)来生成初始化对象,同时让TypeScript匹配到目标类型。

方法1:直接基于数组生成

先过滤出type: 'raw'的元素,再用reduce把它们的id作为键,统一赋值为0:

const initialValue: test = items
  .filter(item => item.type === 'raw')
  .reduce((acc, item) => {
    acc[item.id] = 0;
    return acc;
  }, {} as test);

这里用as test做类型断言是因为reduce的初始值{}默认是空对象类型,需要告诉TypeScript最终结果符合test的结构。

方法2:封装通用工具函数

如果需要多次复用这种初始化逻辑,可以写一个通用函数,自动推导目标类型:

function createInitialValue<T extends {id: string, type: string}>(
  items: readonly T[],
  targetType: string
): Record<Extract<T, {type: typeof targetType}>['id'], number> {
  return items
    .filter(item => item.type === targetType)
    .reduce((acc, item) => {
      acc[item.id] = 0;
      return acc;
    }, {} as any);
}

// 使用示例
const initialValue = createInitialValue(items, 'raw');
// 此时initialValue的类型会自动推导为{ id1: number; id2: number; id3: number; },和test完全一致

为什么直接用类型的写法不行?

你尝试的[key in keyof typeof RawId ]: 0写法本质错误:RawId是类型,不是运行时的值,typeof只能用于获取运行时值的类型,没法反过来操作类型。类型在编译后会被完全擦除,运行时根本不存在RawId这个东西,所以必须基于实际存在的items数组来生成对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:03:32