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

如何类型安全地将唯一判别式联合对象数组转为映射对象

类型安全地将判别式联合数组转换为键值对象

问题分析

你遇到的类型错误本质是:TypeScript无法推断出当前遍历的curr对象,与acc[curr.discriminator]对应的具体联合成员类型完全匹配。虽然你的Mapped映射类型定义正确,但reduce回调中,curr是Discriminated联合类型,而acc[K]的类型是该键对应的具体联合分支,两者在TypeScript的类型检查中无法直接匹配。

解决方案

方法1:使用Extract类型断言(无any)

通过Extract工具类型精准提取当前curr对应的联合分支类型,再进行类型断言,让TypeScript确认类型匹配:

type Discriminated = {
  discriminator: 'a'
  a: string;
} | {
  discriminator: 'b',
  b: number;
}

const arr: Discriminated[] = [
  { discriminator: 'a', a: 'hello' },
  { discriminator: 'b', b: 1 }
];

type Mapped = {
  [D in Discriminated as D['discriminator']]: D;
};

const result = arr.reduce((acc: Mapped, curr) => {
  // 提取curr对应的具体联合分支类型并断言
  acc[curr.discriminator] = curr as Extract<Discriminated, { discriminator: typeof curr.discriminator }>;
  return acc;
}, {} as Mapped);

方法2:泛型辅助函数(自动推断类型)

定义一个泛型函数,让TypeScript根据输入数组自动推断映射后的类型,无需手动断言:

type Discriminated = {
  discriminator: 'a'
  a: string;
} | {
  discriminator: 'b',
  b: number;
}

const arr: Discriminated[] = [
  { discriminator: 'a', a: 'hello' },
  { discriminator: 'b', b: 1 }
];

const reduceToDiscriminatedMap = <T extends { discriminator: string }>(arr: T[]) => {
  return arr.reduce((acc, curr) => {
    acc[curr.discriminator] = curr;
    return acc;
  }, {} as { [K in T['discriminator']]: Extract<T, { discriminator: K }> });
};

// result的类型自动推断为{ a: { discriminator: 'a'; a: string }, b: { discriminator: 'b'; b: number } }
const result = reduceToDiscriminatedMap(arr);

方法3:调整映射类型以匹配目标结构

如果你的目标是去掉discriminator字段(如示例输出所示),可以修改Mapped类型,并在赋值时剔除该字段:

type Discriminated = {
  discriminator: 'a'
  a: string;
} | {
  discriminator: 'b',
  b: number;
}

const arr: Discriminated[] = [
  { discriminator: 'a', a: 'hello' },
  { discriminator: 'b', b: 1 }
];

// 定义去掉discriminator的映射类型
type Mapped = {
  [D in Discriminated as D['discriminator']]: Omit<D, 'discriminator'>;
};

const result = arr.reduce((acc: Mapped, curr) => {
  const { discriminator, ...rest } = curr;
  acc[discriminator] = rest as Omit<typeof curr, 'discriminator'>;
  return acc;
}, {} as Mapped);

原理说明

  • Extract<T, U>工具类型用于从联合类型T中提取符合U约束的分支,精准匹配当前curr的具体类型。
  • 泛型函数通过约束T为包含discriminator的类型,自动推导映射后的键值类型,避免手动重复定义类型。
  • 剔除discriminator字段时,使用Omit<T, K>工具类型确保目标类型与输出结构一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:27:45