【问题标题】:Typescript property does not exist on union type联合类型不存在 Typescript 属性
【发布时间】:2023-01-19 22:30:58
【问题描述】:

这是我遇到过几次的情况,看起来应该相当简单,但我找不到不将类型设置为任何的解决方案

函数将两个不同对象之一作为参数,检查接收到哪个对象,并返回相应的字段。

这是问题的简化版本,但问题是这两个对象只能通过它们的属性(没有重叠)来区分,而且我无法访问任何属性,因为它们不存在于另一个类型。

type Obj1 = {
  message: string
}

type Obj2 = {
  text: string
}

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

  return obj.text
}

【问题讨论】:

    标签: typescript


    【解决方案1】:

    你必须缩小类型。您可以使用 in 运算符来执行此操作。

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

    【讨论】:

    • 这真的让我感到惊讶,因为我曾尝试使用无法编译的 obj.hasOwnProperty('message'),之后我再也不会想到使用 in 运算符。
    • 这应该是公认的答案。使用in 将允许打字稿推断出正确的变量类型,你应该避免显式转换
    • 有什么办法可以在模板中正确地做到这一点?
    • 如果联合类型之一是原始类型怎么办?它给出了一个错误,说你不能将 in 与原语一起使用。
    • TS 如何从中区分类型联合但不能使用可选的链接运算符做到这一点是愚蠢的,即(obj?.message) ? ... : ...
    【解决方案2】:

    您可以将对象转换为 Obj1Obj2

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

    【讨论】:

    • 在“对象 | 字符串”实例中为我工作。谢谢!
    【解决方案3】:

    根据题主的提问,这个问题真正的答案是this

    但是可能有一段时间您以这种方式将your defined typeprimitive type一起使用,上述解决方案将无法解决我遇到的问题 这是情况

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

    所以在这种情况下,上述解决方案对您来说并不完美,因此您可能需要使用typeof✌️

    const getText = (obj: Obj1 | string): string => {
      if (typeof obj !== 'string') {
        return obj.message
      }
    
      return obj.text
    }
    

    【讨论】:

      【解决方案4】:

      我推荐typescript-is

      import { is } from 'typescript-is';
      
      ...
      
      const getText = (obj: Obj1 | Obj2): string => {
        if (is<Obj1>(obj)) {
          return obj1.message;
        }
      
        return obj2.text;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-25
        • 2020-09-27
        • 1970-01-01
        • 2023-04-02
        • 2018-08-17
        • 1970-01-01
        相关资源
        最近更新 更多