我试图理解为什么TS在下面的例子中没有将inst缩小到Bar:

class Foo {}
class Bar { prop = "baz" }

function fn2(inst: Foo | Bar) {
    if (inst instanceof Foo) {
        inst = new Bar()
    }
    inst.prop // prop does not exist on Foo | Bar
}

推荐答案

Typescript是structural,而不是nominal.这里的问题是,Bar的一个实例是assignableFoo类型,所以类型保护实际上没有缩小任何范围.

class Foo {}
class Bar { prop = "baz" }

const inst: Foo = new Bar() // fine

Playground

只有一个属性的对象符合没有属性的对象的接口,因为所有属性(都为零)都被考虑在内.


要实现这一点,需要使这两个类具有不同的接口.

class Foo { foo = 'foo' }
class Bar { bar = 'bar' }

declare let inst: Foo | Bar

if (inst instanceof Foo) inst = new Bar()
inst.bar // works
inst.foo // error

Playground


或者在您的具体情况下:

class Foo { foo = 'foo' }
class Bar { bar = 'bar' }

function fn2(inst: Foo | Bar) {
    if (inst instanceof Foo) {
        inst = new Bar()
    }
    inst.bar
}

Playground

Typescript相关问答推荐

"@ clerker/nextjs/server没有名为clerkMiddleware的导入成员'

当类型断言函数返回假时,TypScript正在推断从不类型

了解TS类型参数列表中的分配

需要使用相同组件重新加载路由变更数据—React TSX

我们过go 不能从TypeScript中的联合中同时访问所有属性?

如果存在ts—mock—imports,我们是否需要typescpt中的IoC容器

使Typescribe强制所有对象具有相同的 struct ,从两个选项

不推荐使用Marker类-Google map API警告

向NextAuth会话添加除名称、图像和ID之外的更多详细信息

如何判断对象是否有重叠的叶子并产生有用的错误消息

如何将所有props传递给React中的组件?

为什么不能使用$EVENT接收字符串数组?

如何缩小函数的返回类型?

创建Angular 为17的动态形状时出错

是否有可能避免此泛型函数体中的类型断言?

在Cypress中,是否可以在不标识错误的情况下对元素调用.Click()方法?

将对象的属性转换为正确类型和位置的函数参数

将布尔值附加到每个对象特性

我可以在 Typescript 中重用函数声明吗?

在 next.js 13.4 中为react-email-editor使用forwardRef和next/dynamic的正确方法