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> fruitStringfruitString 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'不能分配给类型的主要内容,如果未能解决你的问题,请参考以下文章

带领学弟学妹了解TypeScript数据类型

TypeScript入门 - 类型定义函数枚举接口

TypeScript 基础 — string 和 String 的区别

TypeScript-基础-04-联合类型

TypeScript-基础-06-数组的类型

typescript变量定义