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

TypeScript中同类型数组推导的新数组为何类型不一致?

TypeScript数组取值构造新数组时类型推导不一致问题

问题现象

两个类型均为(0 | 1 | 2)[]的数组,取元素构造新数组时,得到的类型推导结果不同:一个保留了字面量联合类型(0 | 1 | 2)[],另一个被加宽为number[]。
复现代码如下:

// 显式标注类型:const nums: (0 | 1 | 2)[]
const nums: (0 | 1 | 2)[] = [];

// 推导结果:let tuple: (0 | 1 | 2)[]
let tuple = [nums[0], nums[1]];


// 隐式推导类型,鼠标悬浮提示为const nums2: (0 | 1 | 2)[]
const nums2 = ([] as {num?: 1 | 2}[]).
    map(n => typeof n.num === "undefined" ? 0 : n.num)

// 推导结果:let tuple2: number[]
let tuple2 = [nums2[0], nums2[1]];

根本原因

类型推导结果差异来自TypeScript的字面量类型加宽规则:

  1. 第一个nums是显式标注了(0 | 1 | 2)[]类型,索引访问得到的元素类型固定为0 | 1 | 2,构造新数组时不会触发加宽,因此tuple类型正确。
  2. 第二个nums2的类型是TS通过Array.prototype.map的泛型返回值自动推导的,没有显式类型标注。TS对这类隐式推导得到的泛型返回值,在后续做索引访问时,会默认将字面量类型加宽为对应的原始类型:即0 | 1 | 2被加宽为number,因此两个元素都是number类型,最终构造出的tuple2就成了number[]。

修复方案

可以任选以下一种方式解决:

  • 显式给nums2标注类型,从根源避免隐式推导带来的加宽问题
const nums2: (0 | 1 | 2)[] = ([] as {num?: 1 | 2}[]).
  map(n => typeof n.num === "undefined" ? 0 : n.num)

// 此时tuple2推导结果为(0 | 1 | 2)[]
let tuple2 = [nums2[0], nums2[1]];
  • 调用map时显式传入泛型参数,固定回调返回值类型
const nums2 = ([] as {num?: 1 | 2}[]).
  map<0 | 1 | 2>(n => typeof n.num === "undefined" ? 0 : n.num)

let tuple2 = [nums2[0], nums2[1]];
  • 给回调返回值加as const断言,阻止字面量类型加宽
const nums2 = ([] as {num?: 1 | 2}[]).
  map(n => (typeof n.num === "undefined" ? 0 : n.num) as const)

let tuple2 = [nums2[0], nums2[1]];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 21:12:19