问答详情
源自:3-1 交叉类型与联合类型

联合类型问题

老师您好:

联合类型产生的新类型只会有共同拥有的属性,例如下面代码:

interface EnglishCourse {
    name: string,
    desc: string
}

interface MathCourse {
    name: number,
    price: number
}

// 联合类型
type Course2 = EnglishCourse | MathCourse;

结果:联合类型Course2打点只有name属性

https://img1.sycdn.imooc.com/659520500001c83b06140121.jpg

但是联合类型还是可以声明desc属性,这是什么原因?

https://img1.sycdn.imooc.com/659520ac00014a7504420124.jpg

提问者:晓之蛇 2024-01-03 16:55

个回答

  • 黑石
    2024-01-09 11:10:40

    1. 这是两种安全策略的问题,分为类型匹配和属性访问限制。


    2. 类型匹配:在你的代码中,变量 c2 被定义为 Course2 类型,这是 EnglishCourse | MathCourse 的联合类型。变量 c2 的结构 { name: 'a', desc: 'abc' } 符合 EnglishCourse 接口的定义(因为 EnglishCoursenamedesc 两个属性),所以 TypeScript 认为这是一个有效的赋值。

            

    接下来,关于为什么你不能直接访问 c2.desc


    1. 属性访问限制:尽管变量 c2 在定义时没有报错,但当你尝试访问 c2 的属性时,TypeScript 变得更加严格。在使用联合类型时,你只能访问所有类型共有的属性。由于 EnglishCourseMathCourse 没有共有的属性(它们的 name 属性类型不同),直接访问 c2.desc 会导致错误。这是因为在不确定 c2 究竟是哪个类型的情况下,直接访问可能不存在的属性是不安全的。

    因此,虽然在定义变量时 TypeScript 允许 c2 匹配 MathCourse 类型,但在后续访问属性时,由于 c2 可能是 EnglishCourse 或 MathCourse,直接访问特定于其中一种类型的属性(如 desc)会导致错误。要安全地访问这些属性,你需要使用类型守卫(如类型断言或 in 关键字检查)来确定 c2 的确切类型。


    这两个方面并不矛盾,而是反映了 TypeScript 在不同场景下的类型安全策略:一方面,在赋值时允许某种程度的灵活性;另一方面,访问属性时则需要更严格的类型确定性。

  • Skywalkerywc
    2024-02-06 18:01:31

    联和行(深圳)贸易有限公司(Liow&Co.)是华润集团旗下跨境(深圳)贸易有限公司,是深圳规模最大、实力最雄厚的跨境贸易企业--华润(集团)有限公司旗下一级利润中心。