首页 > 解决方案 > 当“联合类型上不存在 Typescript 属性”时无法使用变量进行评估

问题描述

这是对联合类型上不存在 Typescript 属性的后续问题。

提供的解决方案是使用in 运算符评估联合中的任一对象。效果很好!这是示例:

type Obj1 = { message: string }
type Obj2 = { text: string }

const getText = (obj: Obj1 | Obj2): string => {
  if ("message" in obj) {
    return obj.message
  }

  return obj.text
}

但是,当我尝试使用变量对其进行评估时,会发生相同的错误:

const getText = (obj: Obj1 | Obj2): string => {
   let property = "message"

   if (property in obj) {
      return obj.message
   }

   return obj.text
}

我只是错过了一些非常明显的东西吗?

标签: javascripttypescripttypesunion-types

解决方案


Typescript 不相信当键是变量(而不是文字)时,像这样的条件实际上会缩小类型。您可以告诉这一点,因为当您将鼠标悬停在条件分支中的 obj 上时,它会报告一种Obj1 | Obj2.

看起来编译器应该能够解决这个问题并知道它是安全的,但是 typescript 编译器并不完美。但它的设计目的是偏向悲观主义,因为过度报告问题比让问题溜进生产代码更危险。

这种情况似乎是一个很大的限制。但在实践中,它不会出现太多。您的代码要求message属性在该条件下可用。使用变量进行测试没有任何意义,因为为了获得类型安全的代码,它只能是property. 因此,您不妨在测试中只使用文字字符串。


但是,如果您对此进行了很多测试,并且希望避免一遍又一遍地输入 sam 文字,则可以创建一个简单的可重用类型保护函数来执行此操作:

function isObj1(obj: Obj1 | Obj2): obj is Obj1 {
    return 'message' in obj
}

const getText = (obj: Obj1 | Obj2): string => {
   if (isObj1(obj)) {
      return obj.message
   }

   return obj.text
}

操场


推荐阅读