Recently, I encountered an issue while trying to create objects that adhere to a specific type annotation (Cards
). The challenge was with a property that needed to match a discriminated union of string literals (CardType
). These string literals were identical to the ones on the original type annotation.
// ------------ SETTING UP ------------
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"' cannot be assigned to type '"Splash"'.ts(2352)
This got me thinking, why did the first example fail while the last two examples executed as expected?
const example1: Cards = {
type
}
Even though example1
appears to meet the requirements of the Cards
type, assigning any value other than explicitly stated string literals like About
or Splash
created issues. It seems to struggle when dealing with a discriminated union.
I apologize if my explanation isn't clear enough!
This discussion on why TypeScript converts string literal union types to strings during assignment may shed some light on the situation.