Тип аннотации и различное объединение строковых литералов - PullRequest
1 голос
/ 15 апреля 2019

У меня возникла эта проблема с созданием объектов, соответствующих аннотации типа (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, он будет работать нормально, это просто когда он может быть распознаваемым объединением что у него есть проблемы.

Извините, я не знаю, как спросить это лучше!

Я чувствую, что, может быть, это так: Почему TypeScript преобразует строковый литерал в объединяющий тип строки при присваивании в литерал объекта? предлагает некоторые подсказки относительно того, почему это происходит?

1 Ответ

1 голос
/ 15 апреля 2019

За исключением тривиальных случаев, когда нет других свойств, { 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: ""
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...