给定以下类型定义:

type A = { a: string } | { a?: undefined; b: string }

这基本上意味着,如果您提供a,那么这就是您应该提供的全部内容.如果您没有提供a,或者您提供了a但它是undefined,则您还必须提供b

如果根据下面的代码未定义a,我希望能够访问b:

let t = true
// The purpose in this line of code is to confuse the compiler such that it won't narrow the definition right in this line of code.
const z: A = t ? { a: 'a' } : { b: 'b' }

if (z.a) {
  console.log(z.a)
} else {
  console.log(z.b)
}

我得到的是以下错误消息::

Property 'b' does not exist on type 'A'.
  Property 'b' does not exist on type '{ a: string; }'

这里有一个link to ts的playground ,带有相关代码.

我期待一个类型安全的解决方案.即不使用不安全字符串(例如hasOwnProperty('b'))测试属性存在性,也不使用类型断言.

这可能吗?

推荐答案

我得到的是以下错误消息::

Property 'b' does not exist on type 'A'.
  Property 'b' does not exist on type '{ a: string; }'

您收到该错误消息的原因是,进入else块时,z.a属性上仍然有一个字符串.如果z.a是空字符串"",就会发生这种情况.所以事实上在其他情况下类型根本没有缩小.

如果您将其切换为此,它就会起作用:

if (typeof z.a === 'string') {
  console.log(z.a)
} else {
  console.log(z.b)
}

Playground link

Typescript相关问答推荐

Typescript联合类型-字段类型覆盖

使用新控制流的FormArray内部的Angular FormGroup

Angular 17 -如何在for循环内创建一些加载?

异步动态生成Playwright测试,显示未找到测试

如何按不能保证的功能过滤按键?

编剧错误:正在等待Expect(Locator).toBeVisible()

角效用函数的类型推断

诡异的文字类型--S为物语的关键

如何在react组件中使用doctype和html标签?

刷新页面时,TypeScrip Redux丢失状态

刷新时保持当前名称的Angular

如何使用TypeScrip在EXPO路由链路组件中使用动态路由?

Typescript,如何在通过属性存在过滤后重新分配类型?

类型实例化过深,可能是无限的&TypeScrip中的TupleUnion错误

使用Cypress测试从Reaction受控列表中删除项目

如何使函数参数数组不相交?

有没有一种方法可以提升对象的泛型级别,而对象的值是泛型函数?

如何处理可能为空的变量...我知道这不是Null?

使用NextJS中间件重定向,特定页面除外

基于参数的 TS 返回类型