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
相关产品推荐
相关产品推荐

