Есть несколько ситуаций, которые приведут вас к этой конкретной ошибке. В случае OP было значение, определенное явно как строка . Поэтому я должен предположить, что, возможно, это произошло из-за раскрывающегося списка, веб-службы или необработанной строки JSON.
В этом случае простое приведение <Fruit> fruitString
или fruitString as Fruit
единственное решение (см. Другие ответы). Вы никогда не сможете улучшить это во время компиляции. [ Редактировать: Смотрите мой другой ответ о<const>
]!
Тем не менее, очень легко столкнуться с этой же ошибкой при использовании констант в вашем коде, которые никогда не предназначались для типа string . Мой ответ сосредоточен на втором сценарии:
Прежде всего: почему «магические» строковые константы часто лучше, чем перечисление?
- Мне нравится, как выглядит строковая константа по сравнению с enum - она компактна и «javascripty»
- Имеет больше смысла, если используемый вами компонент уже использует строковые константы.
- Необходимость импортировать 'enum type' только для получения значения перечисления может быть проблематичной сама по себе
- Что бы я ни делал, я хочу, чтобы он был безопасным для компиляции, поэтому, если я добавлю удалить допустимое значение из типа объединения или неправильно наберет его, тогда он ДОЛЖЕН вызвать ошибку компиляции.
К счастью, когда вы определите:
export type FieldErrorType = 'none' | 'missing' | 'invalid'
... вы на самом деле определяете объединение типов, где 'missing'
на самом деле есть тип!
Я часто сталкиваюсь с ошибкой «не присваивается», если у меня есть строка, как 'banana'
в моем машинописном тексте, и компилятор думает, что я имел в виду это как строку, тогда как я действительно хотел, чтобы она имела типbanana
. Насколько умным может быть компилятор, будет зависеть от структуры вашего кода.
Вот пример того, когда я получил эту ошибку сегодня:
// this gives me the error 'string is not assignable to type FieldErrorType'
fieldErrors: [ { fieldName: 'number', error: 'invalid' } ]
Как только я узнал, что 'invalid'
и 'banana'
может быть либо типа или строки , я понял , что я мог бы просто утверждать строку в этот тип . По сути, приведите его к себе и скажите компилятору, что я не хочу, чтобы это была строка !
// so this gives no error, and I don't need to import the union type too
fieldErrors: [ { fieldName: 'number', error: <'invalid'> 'invalid' } ]
Так что не так с просто «приведение» к FieldErrorType
(или Fruit
)
// why not do this?
fieldErrors: [ { fieldName: 'number', error: <FieldErrorType> 'invalid' } ]
Это не безопасное время компиляции:
<FieldErrorType> 'invalidddd'; // COMPILER ALLOWS THIS - NOT GOOD!
<FieldErrorType> 'dog'; // COMPILER ALLOWS THIS - NOT GOOD!
'dog' as FieldErrorType; // COMPILER ALLOWS THIS - NOT GOOD!
Зачем? Это машинопись, так <FieldErrorType>
что это утверждение, и вы говорите компилятору, что собака является FieldErrorType ! И компилятор это позволит!
НО, если вы сделаете следующее, то компилятор преобразует строку в тип
<'invalid'> 'invalid'; // THIS IS OK - GOOD
<'banana'> 'banana'; // THIS IS OK - GOOD
<'invalid'> 'invalidddd'; // ERROR - GOOD
<'dog'> 'dog'; // ERROR - GOOD
Просто следите за глупыми опечатками, такими как это:
<'banana'> 'banan'; // PROBABLY WILL BECOME RUNTIME ERROR - YOUR OWN FAULT!
Другой способ решения проблемы - приведение родительского объекта:
Мои определения были следующими:
тип экспорта FieldName = 'число' | 'expirationDate' | 'CVV'; тип экспорта FieldError = 'none' | «отсутствует» | 'недействительным'; тип экспорта FieldErrorType = {field: FieldName, ошибка: FieldError};
Допустим, мы получили ошибку с этим (строка не присваиваемая ошибка):
fieldErrors: [ { field: 'number', error: 'invalid' } ]
Мы можем «утверждать» весь объект FieldErrorType
следующим образом:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
Тогда мы избегаем необходимости делать <'invalid'> 'invalid'
.
Но как насчет опечаток? Не <FieldErrorType>
просто утверждать, что имеет право быть такого типа. Не в этом случае - к счастью, компилятор будет жаловаться, если вы сделаете это, потому что он достаточно умен, чтобы знать, что это невозможно:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
export type Fruit
?