首页 > 解决方案 > 是否可以使用可选链接来缩小联合类型的范围?

问题描述

我有一个有区别的 union,简化为这个例子。

type FoobarEvent = FooEvent | BarEvent;

interface FooEvent {
    type: 'foo';
    foo: {
        name: string;
    }
}

interface BarEvent {
    type: 'bar';
    bar: {
        id: string;
    }
}

当然,我可以检查判别式并正确缩小联合类型。

// let's assume this exists
declare const foobarEvent: FoobarEvent;

let fooName: string | undefined;

if (foobarEvent.type === 'foo') {
    fooName = foobarEvent.foo.name;
}

但是我想避免这个 if 块,所以我尝试使用可选链接来缩小类型,但这不起作用,因为其中一个联合没有我试图访问的字段。

const fooNameByChaining = foobarEvent.foo?.name;

“FoobarEvent”类型上不存在属性“foo”。
 “BarEvent”类型上不存在属性“foo”。

因此,显然缩小需要在可选链接之前发生。这是 TypeScript 类型系统的限制,还是可以将其作为一项功能添加到 TypeScript 中?还是有另一种我不知道的解决方法?

游乐场链接

标签: typescript

解决方案


如果 TypeScript 允许您附加.foo?.name任何类型,那么每当我们使用?.运算符时,它都会使类型检查失败。

例如,是 myfoobarEvent的一种类型,其中foo是可选属性:

type FoobarEvent = {
    id: number;
    bar: string;
    foo?: {
        name: string;
    }
}

在这种情况下,我的意图是正确的:

const name = foobarEvent.foo?.name;

或者 - 我是否通过添加.foo?.name错误的类型来创建错字?

const name = localStorage.foo?.name;

推荐阅读