类型注释和可区分的字符串文字联合

Type annotations and discriminated union's of string literals

我在创建符合类型注释(下面示例中的Cards)的对象时遇到了这个问题,属性 是一种可区分的联合类型字符串文字(下例中的 CardType),这些字符串文字与原始类型注释上的字符串文字完全相同。

// ------------ SETUP ------------
interface AboutCard {
  type: 'About'
}

interface SplashCard {
  type: 'Splash'
}

export type Cards = AboutCard | SplashCard
export type CardType = 'About' | 'Splash'

const type = 'About' as CardType
// ------------ SETUP END ------------

const example1: Cards = {
  type
}

// ^
// Type 'CardType' is not assignable to type '"Splash"'.
// Type '"About"' is not assignable to type '"Splash"'.ts(2322)

const example2 = {
  type
} as Cards

// ^ all good, no error.

const example3 = {
  type: 'NOT_REAL_CARD'
} as Cards

// ^
// Types of property 'type' are incompatible.
// Type '"NOT_REAL_CARD"' is not comparable to type '"Splash"'.ts(2352)

所以基本上我想知道为什么第一个例子:

const example1: Cards = {
  type
}

失败了,但最后两个例子符合我的预期。

example1 似乎符合类型 Cards,如果您尝试将 type 显式设置为字符串文字 AboutSplash 它工作正常,只是当它可能是受歧视的工会时,它才有问题。

对不起,我不知道怎么问才好!

我觉得可能是这样的: 提供了一些关于为什么会发生这种情况的线索?

除了没有其他属性的微不足道的情况外,{ type: 'About' | 'Splash' }{ type: 'About' } | { type: 'Splash' } 不同。由于您的变量 type 是所有可能判别式的并集,因此您正试图做到这一点,将一个键为 type 的对象分配给一个被判别联合 属性 的对象预计。

后两个示例之所以有效,是因为您几乎可以使用类型断言做任何事情。您实际上是在告诉编译器抑制它认为存在的类型错误。

要了解为什么这些类型不兼容,请考虑以下示例:

interface AboutCard {
    type: 'About'
    aboutMessage: string
}

interface SplashCard {
    type: 'Splash'
    spashMessage: string
}

export type Cards = AboutCard | SplashCard
export type CardType = Cards['type'] // no need to repeat string liteal types

const type = 'About' as CardType

// What properties should be required for `example1` ? 
// since it is both types at the same time best case scenario would be to require all properties in teh union
const example1: Cards = {
    type,
    spashMessage: ""
}