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

TypeScript遍历数组时保留判别联合类型的简洁方案问询

TypeScript判别联合类型数组映射的类型错误解决办法

问题背景

定义了一个带判别式的联合类型数组:

const array: (
  | { foo: true; bar: [number, number] }
  | { foo: false; bar: [number, number, number] }
)[] = [
  { foo: true, bar: [1, 2] },
  { foo: false, bar: [3, 4, 5] },
];

需求是将数组中所有数字翻倍,尝试用以下代码实现:

// 该函数逻辑正确,无需分析
export const mapTuple = <T extends unknown[], R>(
  array: T,
  callback: (value: T[number], index: number, array: T) => R,
): { [K in keyof T]: R } =>
  array.map(
    callback as (value: unknown, index: number, array: unknown[]) => R,
  ) as { [K in keyof T]: R };

const result: typeof array = array.map(({ foo, bar }) => ({
  foo,
  bar: mapTuple(bar, (x) => x * 2),
}));

但出现类型错误:Type 'boolean' is not assignable to type 'false'。目前临时解决方案是用冗余的三元表达式:

const result: typeof array = array.map(({ foo, bar }) =>
  foo
    ? { foo, bar: mapTuple(bar, (x) => x * 2) }
    : { foo, bar: mapTuple(bar, (x) => x * 2) },
);

简洁解决方案

方案1:提取处理逻辑到单独函数

将单个元素的处理逻辑抽成独立函数,TypeScript会自动基于输入的联合类型推断正确的返回类型,保留foo的字面量类型:

const processItem = (item: typeof array[number]) => ({
  foo: item.foo,
  bar: mapTuple(item.bar, x => x * 2)
});

const result: typeof array = array.map(processItem);

方案2:使用as const断言保留字面量类型

在对象字面量中对foo使用as const断言,阻止TypeScript将其类型拓宽为boolean:

const result: typeof array = array.map(({ foo, bar }) => ({
  foo: foo as const,
  bar: mapTuple(bar, (x) => x * 2),
}));

原因说明

直接在map回调中返回对象字面量时,TypeScript会把foo的类型从字面量true/false拓宽为通用的boolean,导致无法匹配原联合类型的分支要求。上述两种方案都能避免类型拓宽,让TypeScript正确识别返回值的联合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:05:16