Є кілька ситуацій, які дадуть вам саме цю помилку. У випадку з ОП було значення, визначене явно як рядок . Тож я маю припустити, що, можливо, це сталося із спадного меню, веб-сервісу чи необробленої рядки JSON.
У цьому випадку простий склад <Fruit> fruitString
або fruitString as Fruit
єдине рішення (див. Інші відповіді). Ви ніколи не зможете покращити це під час компіляції. [ Редагувати: див. Мою іншу відповідь про<const>
]!
Однак зіткнутися з цією самою помилкою дуже просто при використанні констант у вашому коді, які ніколи не повинні мати тип рядка . Моя відповідь зосереджена на тому другому сценарії:
Перш за все: чому "магічні" струнні константи часто кращі за перерахунок?
- Мені подобається, як струнна константа виглядає проти перерахунку - вона компактна і "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 = 'число' | 'дата закінчення' | 'cvv'; тип експорту FieldError = 'немає' | 'відсутній' | 'недійсний'; тип експорту FieldErrorType = {поле: 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
?