我一直遇到这个问题,创建符合类型注释的对象(下例中的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
设置为字符串文字About
或Splash
它工作正常,它就是它可能是它有问题的歧视联盟。
对不起,我不知道如何更好地问这个!
我觉得这可能是这样的:why is TypeScript converting string literal union type to string when assigning in object literal?提供了一些关于为什么会发生这种情况的线索?
除了没有其他属性的琐碎案例,{ 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: ""
}