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

遍历联合类型数组时TypeScript编译器抛出异常错误

TypeScript循环中联合类型数组的类型收窄失效问题

先看你遇到的问题代码:

type RandomType = {x: number, y: number}
type UnifiedTypes = RandomType | 0

type ArrayOfTypes = Array<(RandomType | UnifiedTypes)[]>

const newIns: ArrayOfTypes = [[0, {x: 10, y: 201}], [0, {x: 10, y: 201}]]

for(let i=0; i < newIns.length; ++i){
    for(let j=0; j < newIns[i].length; ++j){
        if(newIns[i][j] !== 0){
            newIns[i][j].x = 30 // Property 'x' does not exist on type 'UnifiedTypes'. Property 'x' does not exist on type '0'
        }
    }
}

// 但在循环外使用字面量索引时没有问题
if(newIns[0][0] !== 0) {
   newIns[0][0].x = 33; // 无报错
}

问题原因

这是TypeScript类型检查器的局限性:当使用可变变量(比如i、j)作为数组索引时,编译器无法跟踪newIns[i][j]的类型在条件判断后是否依然保持收窄状态。因为变量i和j的值是动态变化的,编译器没办法确保在if(newIns[i][j] !== 0)判断之后,这个索引对应的元素没有被其他代码修改,或者索引本身有没有被重新赋值,所以它不会为这个动态索引的表达式维持收窄后的类型。

而使用**字面量索引(比如0)**时,编译器能明确知道这个固定位置的元素类型,判断后可以安全收窄类型,所以不会报错。

解决方案

有两种简单的方式解决这个问题:

1. 使用临时变量存储数组元素

把循环中当前索引的元素赋值给一个const临时变量,编译器能跟踪这个变量的类型,收窄后就可以安全访问属性:

for(let i=0; i < newIns.length; ++i){
    for(let j=0; j < newIns[i].length; ++j){
        const item = newIns[i][j];
        if(item !== 0){
            item.x = 30; // 正常编译,无报错
        }
    }
}

2. 使用数组的forEach方法遍历

forEach的回调参数会被自动推导类型,并且类型收窄能正常生效:

newIns.forEach(arr => {
    arr.forEach(item => {
        if(item !== 0){
            item.x = 30; // 正常工作
        }
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 19:06:20