Вот что у меня в fruit.ts
export type Fruit = "Orange" | "Apple" | "Banana"
Сейчас я импортирую fruit.ts в другой машинописный файл. Вот что у меня есть
myString:string = "Banana";
myFruit:Fruit = myString;
Когда я делаю
myFruit = myString;
Я получаю ошибку:
Тип 'string' нельзя назначить типу "" Orange "| "Яблоко" | "Банан"'
Как я могу присвоить строку переменной пользовательского типа Fruit?
javascript
typescript
angular
user6123723
источник
источник
export type Fruit
?Ответы:
Вам нужно будет разыграть это :
Также обратите внимание, что при использовании строковых литералов вам нужно использовать только один
|
редактировать
Как упоминалось в другом ответе @Simon_Weaver, теперь можно утверждать, что
const
:источник
const myFruit: Fruit = "Banana"
подойдет.let myFruit:Fruit = "Apple" let something:string = myFruit as string
Это дает мне ошибку: преобразование типа 'Fruit' в тип 'string' может быть ошибкой.as string
роль. Я попробовал ваш код на детской площадке, и там нет ошибок.const myString: string = 'Bananaaa';
я не получаю ошибки компиляции из-за приведения ... нет ли способа сделать это во время проверки типа строки?Typescript
3.4
вводит новое утверждение constТеперь вы можете предотвратить «расширение» литеральных типов (например,
'orange'
или'red'
)string
с помощью так называемогоconst
утверждения.Вы сможете сделать:
И тогда он больше не превратится в себя
string
- что является корнем проблемы в этом вопросе.источник
let fruit = 'orange' as const;
при соблюдении правила утверждения типа без угловых скобокКогда вы делаете это:
... вы создаете тип с именем,
Fruit
который может содержать только литералы"Orange"
,"Apple"
и"Banana"
. Этот тип расширяетсяString
, следовательно, он может быть назначенString
. ОднакоString
НЕ расширяется"Orange" | "Apple" | "Banana"
, поэтому его нельзя назначить.String
является менее определенным . Это может быть любая строка .Когда вы делаете это:
...оно работает. Зачем? Поскольку фактический тип из
myString
в этом примере"Banana"
. Да,"Banana"
это тип . Он расширяется,String
поэтому его можно назначитьString
. Кроме того, тип расширяет тип объединения, когда он расширяет любой из его компонентов. В этом случае"Banana"
тип расширяется,"Orange" | "Apple" | "Banana"
поскольку расширяет один из его компонентов. Следовательно,"Banana"
присваивается"Orange" | "Apple" | "Banana"
илиFruit
.источник
<'Banana'> 'Banana'
и это «приведёт»"Banana"
строку к"Banana"
типу !!!<const> 'Banana'
что лучше :-)Я вижу, что это немного старый, но здесь может быть лучшее решение.
Если вам нужна строка, но вы хотите, чтобы строка соответствовала только определенным значениям, вы можете использовать перечисления .
Например:
Теперь вы будете знать, что несмотря ни на что, myFruit всегда будет строкой "Banana" (или любым другим перечисляемым значением, которое вы выберете). Это полезно для многих вещей, будь то группировка похожих значений, подобных этой, или отображение удобных для пользователя значений в удобные для машины значения, все это при одновременном применении и ограничении значений, разрешенных компилятором.
источник
let myFruit: Fruit = "Banana"
.Есть несколько ситуаций, которые приведут вас к этой конкретной ошибке. В случае OP было значение, определенное явно как строка . Поэтому я должен предположить, что, возможно, это произошло из-за раскрывающегося списка, веб-службы или необработанной строки JSON.
В этом случае простое приведение
<Fruit> fruitString
илиfruitString as Fruit
единственное решение (см. Другие ответы). Вы никогда не сможете улучшить это во время компиляции. [ Редактировать: Смотрите мой другой ответ о<const>
]!Тем не менее, очень легко столкнуться с этой же ошибкой при использовании констант в вашем коде, которые никогда не предназначались для типа string . Мой ответ сосредоточен на втором сценарии:
Прежде всего: почему «магические» строковые константы часто лучше, чем перечисление?
К счастью, когда вы определите:
export type FieldErrorType = 'none' | 'missing' | 'invalid'
... вы на самом деле определяете объединение типов, где
'missing'
на самом деле есть тип!Я часто сталкиваюсь с ошибкой «не присваивается», если у меня есть строка, как
'banana'
в моем машинописном тексте, и компилятор думает, что я имел в виду это как строку, тогда как я действительно хотел, чтобы она имела типbanana
. Насколько умным может быть компилятор, будет зависеть от структуры вашего кода.Вот пример того, когда я получил эту ошибку сегодня:
Как только я узнал, что
'invalid'
и'banana'
может быть либо типа или строки , я понял , что я мог бы просто утверждать строку в этот тип . По сути, приведите его к себе и скажите компилятору, что я не хочу, чтобы это была строка !Так что не так с просто «приведение» к
FieldErrorType
(илиFruit
)Это не безопасное время компиляции:
Зачем? Это машинопись, так
<FieldErrorType>
что это утверждение, и вы говорите компилятору, что собака является FieldErrorType ! И компилятор это позволит!НО, если вы сделаете следующее, то компилятор преобразует строку в тип
Просто следите за глупыми опечатками, такими как это:
Другой способ решения проблемы - приведение родительского объекта:
Мои определения были следующими:
тип экспорта FieldName = 'число' | 'expirationDate' | 'CVV'; тип экспорта FieldError = 'none' | «отсутствует» | 'недействительным'; тип экспорта FieldErrorType = {field: FieldName, ошибка: FieldError};
Допустим, мы получили ошибку с этим (строка не присваиваемая ошибка):
Мы можем «утверждать» весь объект
FieldErrorType
следующим образом:Тогда мы избегаем необходимости делать
<'invalid'> 'invalid'
.Но как насчет опечаток? Не
<FieldErrorType>
просто утверждать, что имеет право быть такого типа. Не в этом случае - к счастью, компилятор будет жаловаться, если вы сделаете это, потому что он достаточно умен, чтобы знать, что это невозможно:источник
Все вышеприведенные ответы верны, однако в некоторых случаях строковый литеральный тип является частью другого сложного типа. Рассмотрим следующий пример:
У вас есть несколько решений, чтобы это исправить. Каждое решение является действительным и имеет свои варианты использования.
1) Первое решение - определить тип для размера и экспортировать его из foo.ts. Это хорошо, если вам нужно работать с параметром размера самостоятельно. Например, у вас есть функция, которая принимает или возвращает параметр размера шрифта, и вы хотите его ввести.
2) Второй вариант - просто привести его к типу ToolbarTheme. В этом случае вам не нужно открывать внутреннюю часть ToolbarTheme, если вам это не нужно.
источник
Если вы приводите,
dropdownvalue[]
к примеру, при манипулировании данными, составьте их как массив объектов со свойствами value и display.пример :
источник
Я столкнулся с той же проблемой, я внес следующие изменения, и проблема была решена.
Открыть файл watchQueryOptions.d.ts
Изменить тип запроса любой вместо DocumentNode , То же самое для мутации
Перед:
После:
источник