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

为何Promise.allSettled+forEach后TypeScript将值推断为never类型?

问题原因

TypeScript的控制流分析无法跨函数回调跟踪变量赋值,这是核心问题。

你用Array.forEach()处理Promise.allSettled的结果时,forEach的回调是一个独立函数。TypeScript无法确保这个回调会被执行(即便我们明确知道数组有2个元素、回调会执行2次,但TS的静态分析不会做这么深入的假设),因此它无法识别到回调里对value和value2的赋值操作。

在后续的if (!value || !value2) throw检查中,TS会认为value和value2始终是初始的undefined,因此这个throw语句永远会触发,后面的代码属于不可达代码,变量类型就被推断为never。

解决方案

不用forEach,改用普通for循环或者直接解构allSettled的结果,让TS能跟踪控制流:

方案1:普通for循环

把forEach替换成索引循环或for...of,TS能直接跟踪循环内的变量赋值:

type myValue = {
    test1: string;
    test2: string;
    test3: string;
} | undefined;

const go = async () => {
    let value: myValue = undefined;
    let value2: myValue = undefined;

    const results = await Promise.allSettled([
        Promise.resolve({test1: 'test1.1', test2: 'test2.1', test3: 'test3.1'}),
        Promise.resolve({test1: 'test1.2', test2: 'test2.2', test3: 'test3.2'}),
    ]);

    // 改用索引循环
    for (let index = 0; index < results.length; index++) {
        const result = results[index];
        if (result.status === "fulfilled") {
            if (index === 0) {
                value = result.value;
            }
            if (index === 1) {
                value2 = result.value;
            }
        } else {
            console.error("error", result.reason);
        }
    }

    if (!value || !value2) {
        throw new Error("no Value found");
    }

    // TS现在能正确推断类型
    console.log("value.test1:", value.test1);
    console.log("value2.test3:", value2.test3);
}

go();

方案2:直接解构结果

既然你明确知道数组有2个元素,直接解构allSettled的结果,更简洁且TS能完美推断:

type myValue = {
    test1: string;
    test2: string;
    test3: string;
} | undefined;

const go = async () => {
    const [result1, result2] = await Promise.allSettled([
        Promise.resolve({test1: 'test1.1', test2: 'test2.1', test3: 'test3.1'}),
        Promise.resolve({test1: 'test1.2', test2: 'test2.2', test3: 'test3.2'}),
    ]);

    let value: myValue = undefined;
    let value2: myValue = undefined;

    if (result1.status === "fulfilled") {
        value = result1.value;
    } else {
        console.error("error in result1", result1.reason);
    }

    if (result2.status === "fulfilled") {
        value2 = result2.value;
    } else {
        console.error("error in result2", result2.reason);
    }

    if (!value || !value2) {
        throw new Error("no Value found");
    }

    console.log("value.test1:", value.test1);
    console.log("value2.test3:", value2.test3);
}

go();
补充说明

TS的控制流分析是局部性的,它不会跨函数调用跟踪变量状态。类似forEach、map这类接受回调的数组方法,TS都无法识别回调内对外部变量的修改。改用同步的循环结构(for、for...of)或者直接处理每个元素,就能让TS正确推断类型,不需要类型断言或忽略错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:40:13