如何类型安全地将唯一判别式联合对象数组转为映射对象
类型安全地将判别式联合数组转换为键值对象
问题分析
你遇到的类型错误本质是: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
相关产品推荐
相关产品推荐

