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

为什么TypeScript无法收窄可辨识联合类型导致函数调用报错

报错原因

TypeScript 不会跟踪不同变量之间的类型关联关系,你把fn和arg从联合类型对象中解构出来之后,两个变量的类型会被独立推导:

  • fn的类型推导为 ((arg: X) => void) | ((arg: Y) => void)
  • arg的类型推导为 'foo' | 'bar'

由于函数参数属于类型逆变位置,多个函数组成的联合类型,调用时的参数需要满足所有函数的参数要求,也就是所有参数类型的交集。'foo'和'bar'没有公共交集,交集类型就是never,所以你传入任何非never的参数都会报错,哪怕你逻辑上确定这两个值必然来自同一个联合分支,TS也不会做这种跨变量的关联校验。

解决方法

方法1:不解构,直接通过原对象调用

TS会识别同一个联合类型对象上的属性属于同一个分支,直接调用不会报错:

function acceptsUnion(union: DiscriminatedUnion): void {
    union.fn(union.arg);
}

方法2:先根据可辨识字段收窄类型

如果你需要解构,可以先通过type字段做类型收窄,再在每个分支内解构使用:

function acceptsUnion(union: DiscriminatedUnion): void {
    if (union.type === 'X') {
        const {fn, arg} = union;
        fn(arg); // 类型匹配,无报错
    } else {
        const {fn, arg} = union;
        fn(arg); // 类型匹配,无报错
    }
}

方法3:使用泛型约束

如果不想写分支判断,可以用泛型绑定联合类型的分支:

type UnionMap = {
    X: X,
    Y: Y
}
function acceptsUnion<T extends keyof UnionMap>(union: { type: T, fn: (arg: UnionMap[T]) => void, arg: UnionMap[T] }): void {
    const {fn, arg} = union;
    fn(arg);
}

内容的提问来源于stack exchange,提问作者Андрей Фирсов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 00:54:03