这是两种安全策略的问题,分为类型匹配和属性访问限制。
类型匹配:在你的代码中,变量 c2
被定义为 Course2
类型,这是 EnglishCourse | MathCourse
的联合类型。变量 c2 的结构 { name: 'a', desc: 'abc' }
符合 EnglishCourse
接口的定义(因为 EnglishCourse
有 name
和 desc
两个属性),所以 TypeScript 认为这是一个有效的赋值。
接下来,关于为什么你不能直接访问 c2.desc:
属性访问限制:尽管变量 c2
在定义时没有报错,但当你尝试访问 c2
的属性时,TypeScript 变得更加严格。在使用联合类型时,你只能访问所有类型共有的属性。由于 EnglishCourse
和 MathCourse
没有共有的属性(它们的 name
属性类型不同),直接访问 c2.desc
会导致错误。这是因为在不确定
c2
究竟是哪个类型的情况下,直接访问可能不存在的属性是不安全的。
因此,虽然在定义变量时 TypeScript 允许 c2 匹配 MathCourse 类型,但在后续访问属性时,由于 c2 可能是 EnglishCourse 或 MathCourse,直接访问特定于其中一种类型的属性(如 desc)会导致错误。要安全地访问这些属性,你需要使用类型守卫(如类型断言或 in 关键字检查)来确定 c2 的确切类型。
这两个方面并不矛盾,而是反映了 TypeScript 在不同场景下的类型安全策略:一方面,在赋值时允许某种程度的灵活性;另一方面,访问属性时则需要更严格的类型确定性。
啥啊?
是一种后端语言。