Typescript类型'string'不能分配给类型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Typescript类型'string'不能分配给类型相关的知识,希望对你有一定的参考价值。
这就是我在fruit.ts中所拥有的
export type Fruit = "Orange" | "Apple" | "Banana"
现在我在另一个打字稿文件中导入fruit.ts。这就是我所拥有的
myString:string = "Banana";
myFruit:Fruit = myString;
当我做
myFruit = myString;
我收到一个错误:
类型'字符串'不能分配给类型'“Orange”| “Apple”| “香蕉”'
如何将字符串分配给自定义类型Fruit的变量?
你需要cast it:
export type Fruit = "Orange" | "Apple" | "Banana";
let myString: string = "Banana";
let myFruit: Fruit = myString as Fruit;
另请注意,使用string literals时,您只需使用一个|
当你这样做:
export type Fruit = "Orange" | "Apple" | "Banana"
...你正在创建一个名为Fruit
的类型,它只能包含文字"Orange"
,"Apple"
和"Banana"
。这种类型扩展String
,因此它可以分配给String
。但是,String
不会扩展"Orange" | "Apple" | "Banana"
,所以它不能分配给它。 String
不太具体。它可以是任何字符串。
当你这样做:
export type Fruit = "Orange" | "Apple" | "Banana"
const myString = "Banana";
const myFruit: Fruit = myString;
...有用。为什么?因为在这个例子中myString
的实际类型是"Banana"
。是的,"Banana"
就是这种类型。它扩展了String
所以它可以分配给String
。此外,类型在扩展其任何组件时扩展了Union Type。在这种情况下,"Banana"
,类型,扩展"Orange" | "Apple" | "Banana"
,因为它扩展了其中一个组件。因此,"Banana"
可分配给"Orange" | "Apple" | "Banana"
或Fruit
。
Typescript 3.4
引入了新的“const”断言
你现在可以防止文字类型(例如,'orange'
或'red'
)被“扩大”以用所谓的string
断言输入const
。
你将能够做到:
let fruit = <const> 'orange';
然后它不会再变成一个string
- 这是问题中错误的根源。
我觉得这有点旧,但这里可能有更好的解决方案。
如果需要字符串,但希望字符串仅匹配某些值,则可以使用enums。
例如:
enum Fruit
Orange = "Orange",
Apple = "Apple",
Banana = "Banana"
let myFruit: Fruit = Fruit.Banana;
现在你会知道,无论如何,myFruit将始终是字符串“Banana”(或者你选择的任何其他可枚举的值)。这对许多事情都很有用,无论是将类似的值分组,还是将用户友好的值映射到机器友好的值,同时强制执行和限制编译器允许的值。
有几种情况会给你这个特殊的错误。在OP的情况下,存在明确定义为字符串的值。所以我必须假设这可能来自下拉列表,或Web服务或原始JSON字符串。
在这种情况下,一个简单的演员<Fruit> fruitString
或fruitString as Fruit
是唯一的解决方案(见其他答案)。在编译时你永远无法改进这一点。 [编辑:看看我关于<const>
的其他答案]!
但是,在代码中使用常量不是类型字符串的常量时,很容易遇到同样的错误。我的回答集中在第二种情况:
首先:为什么'魔术'字符串常量通常比枚举更好?
- 我喜欢字符串常量与枚举相似的方式 - 它是紧凑的和'javascript'
- 如果您正在使用的组件已使用字符串常量,则更有意义。
- 必须导入'枚举类型'才能获得枚举值本身就很麻烦
- 无论我做什么,我希望它是编译安全的,所以如果我添加从联合类型中删除一个有效的值,或错误键入它然后它必须给出一个编译错误。
幸运的是,当你定义:
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 ='number'| 'expirationDate'| 'CVV';导出类型FieldError ='none'| '失踪'| '无效';导出类型FieldErrorType = field:FieldName,error:FieldError;
假设我们得到一个错误(字符串不可赋值错误):
fieldErrors: [ field: 'number', error: 'invalid' ]
我们可以将整个对象“断言”为像这样的FieldErrorType
:
fieldErrors: [ <FieldErrorType> field: 'number', error: 'invalid' ]
然后我们避免不得不做<'invalid'> 'invalid'
。
打字错误呢?不是<FieldErrorType>
只是断言权利属于那种类型。不是在这种情况下 - 幸运的是编译器会抱怨如果你这样做,因为它很聪明,知道它是不可能的:
fieldErrors: [ <FieldErrorType> field: 'number', error: 'dog' ]
例如,如果您在模拟数据时转换为下拉值[],请将其组合为具有值和显示属性的对象数组。
例如:['value':'test1','display1':'test display','value':'test2','display':'test display2',]
以上是关于Typescript类型'string'不能分配给类型的主要内容,如果未能解决你的问题,请参考以下文章