Javascript 类型脚本类型';字符串';不可分配给类型
这是我的水果Javascript 类型脚本类型';字符串';不可分配给类型,javascript,typescript,angular,Javascript,Typescript,Angular,这是我的水果 export type Fruit = "Orange" | "Apple" | "Banana" 现在我正在另一个typescript文件中导入fruit.ts。这是我的 myString:string = "Banana"; myFruit:Fruit = myString; 当我这样做的时候 myFruit = myString; 我得到一个错误: 类型“string”不可分配给类型“Orange”|“Apple”| “香蕉” 如何将字符串分配给自定义类型Fruit的
export type Fruit = "Orange" | "Apple" | "Banana"
现在我正在另一个typescript文件中导入fruit.ts。这是我的
myString:string = "Banana";
myFruit:Fruit = myString;
当我这样做的时候
myFruit = myString;
我得到一个错误:
类型“string”不可分配给类型“Orange”|“Apple”|
“香蕉”
如何将字符串分配给自定义类型Fruit的变量?您需要:
还请注意,使用时只需使用一个|
编辑
正如@Simon_Weaver在另一个答案中提到的,现在可以将其断言为const
:
let fruit = "Banana" as const;
我知道这有点过时了,但这里可能有更好的解决方案 如果需要字符串,但希望该字符串仅与某些值匹配,则可以使用 例如:
enum Fruit {
Orange = "Orange",
Apple = "Apple",
Banana = "Banana"
}
let myFruit: Fruit = Fruit.Banana;
现在您将知道,无论发生什么,myFruit始终是字符串“Banana”(或您选择的任何其他可枚举值)。这对许多事情都很有用,无论是将类似的值分组,还是将用户友好的值映射到机器友好的值,同时强制和限制编译器允许的值。执行此操作时:
export type Fruit = "Orange" | "Apple" | "Banana"
export type Fruit = "Orange" | "Apple" | "Banana"
const myString = "Banana";
const myFruit: Fruit = myString;
…您正在创建一个名为水果
的类型,该类型只能包含文本“橙色”
、“苹果”
和“香蕉”
。此类型扩展了字符串
,因此可以将其分配给字符串
。但是,字符串
不扩展“橙色”|“苹果”|“香蕉”
,因此无法将其分配给它<代码>字符串不太具体。它可以是任何字符串
执行此操作时:
export type Fruit = "Orange" | "Apple" | "Banana"
export type Fruit = "Orange" | "Apple" | "Banana"
const myString = "Banana";
const myFruit: Fruit = myString;
…它起作用了。为什么?因为本例中
myString
的实际类型是“香蕉”
。是的,“香蕉”
是类型。它扩展了String
,因此可以分配给String
。此外,类型在扩展其任何组件时扩展了联合类型。在本例中,“Banana”
,类型扩展了“Orange”|“Apple”|“Banana”
,因为它扩展了它的一个组件。因此,“香蕉”
可分配给“橙色”|“苹果”|“香蕉”
或水果
有几种情况会导致此特定错误。对于OP,有一个值明确定义为字符串。因此,我必须假设这可能来自下拉列表、web服务或原始JSON字符串
在这种情况下,唯一的解决方案是将水果串
或水果串转换为水果串
(参见其他答案)。在编译时,您永远无法在这方面有所改进。[编辑:请参阅我关于
]的其他答案]
但是,在代码中使用从未打算为string类型的常量时,很容易遇到同样的错误。我的回答集中在第二种情况:
首先:为什么“神奇”字符串常量通常比枚举更好?
- 我喜欢字符串常量相对于枚举的外观-它紧凑且“javascripty”
- 如果您正在使用的组件已经使用了字符串常量,则更有意义
- 仅为了获得枚举值而必须导入“枚举类型”本身可能会很麻烦
- 无论我做什么,我都希望它是编译安全的,因此如果我从联合类型中添加或删除有效值,或者键入错误,那么它必须给出一个编译错误
导出类型FieldErrorType='none'|'missing'|'invalid'
…您实际上是在定义类型的联合,其中,'missing'
实际上是一个类型
如果我的typescript中有一个类似于'banana'
的字符串,而编译器认为它是一个字符串,而我真的希望它是banana
类型,那么我经常会遇到“not assignable”错误。编译器的智能程度取决于代码的结构
下面是我今天遇到这个错误的一个例子:
// 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> 'invalidddd'; // COMPILER ALLOWS THIS - NOT GOOD!
<FieldErrorType> 'dog'; // COMPILER ALLOWS THIS - NOT GOOD!
'dog' as FieldErrorType; // COMPILER ALLOWS THIS - NOT GOOD!
我们可以将整个对象“断言”为FieldErrorType
,如下所示:
<'banana'> 'banan'; // PROBABLY WILL BECOME RUNTIME ERROR - YOUR OWN FAULT!
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
fieldErrors:[{field:'number',error:'invalid'}]
然后我们就不必执行“无效”
但是打字错误呢?不只是断言右边属于该类型的内容。在这种情况下不是这样-幸运的是,如果您这样做,编译器会抱怨,因为它足够聪明,知道这是不可能的:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
fieldErrors:[{field:'number',error:'dog'}]
Typescript引入了新的“const”断言
您现在可以使用所谓的const
断言防止文本类型(例如'orange'
或'red'
)被“加宽”为类型字符串
您将能够做到:
let fruit = 'orange' as const; // or...
let fruit = <const> 'orange';
let fruit='orange'作为常量;//或
让水果=橙色;
然后它就不会再把自己变成字符串了
——这是问题的根源
额外提示:您还可以使用false
或true
来表示必须为true或false的布尔值。这在某些情况下很有用。当您看到它时,您就会知道它。如果您在模拟数据时强制转换为dropdownvalue[]
,请将其组合为具有值和显示属性的对象数组
示例:
[{'value': 'test1', 'display1': 'test display'},{'value': 'test2', 'display': 'test display2'},]
我也面临同样的问题,我做了如下c
let fruit = 'orange' as const; // or...
let fruit = <const> 'orange';
[{'value': 'test1', 'display1': 'test display'},{'value': 'test2', 'display': 'test display2'},]
\apollo-client\core\watchQueryOptions.d.ts
export interface QueryBaseOptions<TVariables = OperationVariables> {
query: **DocumentNode**;
export interface QueryBaseOptions<TVariables = OperationVariables> {
query: **any**;
// in foo.ts
export type ToolbarTheme = {
size: 'large' | 'small',
};
// in bar.ts
import { ToolbarTheme } from './foo.ts';
function useToolbarTheme(theme: ToolbarTheme) {/* ... */}
// Here you will get the following error:
// Type 'string' is not assignable to type '"small" | "large"'.ts(2322)
['large', 'small'].forEach(size => (
useToolbarTheme({ size })
));
// in foo.ts
export type ToolbarThemeSize = 'large' | 'small';
export type ToolbarTheme = {
size: ToolbarThemeSize
};
// in bar.ts
import { ToolbarTheme, ToolbarThemeSize } from './foo.ts';
function useToolbarTheme(theme: ToolbarTheme) {/* ... */}
function getToolbarSize(): ToolbarThemeSize {/* ... */}
['large', 'small'].forEach(size => (
useToolbarTheme({ size: size as ToolbarThemeSize })
));
// in foo.ts
export type ToolbarTheme = {
size: 'large' | 'small'
};
// in bar.ts
import { ToolbarTheme } from './foo.ts';
function useToolbarTheme(theme: ToolbarTheme) {/* ... */}
['large', 'small'].forEach(size => (
useToolbarTheme({ size } as ToolbarTheme)
));
myObject.abcOrD = myStringVar as any;
export type Fruit = "Orange" | "Apple" | "Banana"
export type FruitArray = Fruit[];
const someFruits= ["Banana"];
const workingFruits: FruitArray = ["Orange", "Apple"]; // Works
// Even orange and apple show: Type 'string' is not assignable to type Fruit
const brokenAllFruits: FruitArray = [...someFruits, "Orange", "Apple"];
// As const is needed in the spread array
const someConstFruits= ["Banana" as const];
const workingAllFruits: FruitArray = [...someConstFruits, "Orange", "Apple"]; // Works