这是我的水果。ts

export type Fruit = "Orange" | "Apple" | "Banana"

现在我在进口水果。Ts在另一个typescript文件中。这是我有的

myString:string = "Banana";

myFruit:Fruit = myString;

当我这样做的时候

myFruit = myString;

我得到一个错误:

类型“string”不能赋值给类型“Orange”|“Apple”| “香蕉”

如何将字符串分配给自定义类型水果的变量?


当前回答

当你这样做的时候:

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”。是的,“香蕉”就是那种类型。它是extends String,所以它是可赋值给String的。此外,当一个类型扩展Union type的任何组件时,它也扩展了Union type。在本例中,类型“Banana”扩展了“Orange”|“Apple”|“Banana”,因为它扩展了它的一个组件。因此,“香蕉”可分配给“橙子”|“苹果”|“香蕉”或水果。

其他回答

以上所有答案都是有效的,然而,在某些情况下,字符串文字类型是另一个复杂类型的一部分。考虑下面的例子:

  // 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 })
  ));

你有多种解决方案来解决这个问题。每个解决方案都是有效的,并且有自己的用例。

1)第一个解决方案是为size定义一个类型,并从foot .ts导出它。当您需要单独使用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 })
  ));

2)第二个选项是将其转换为ToolbarTheme类型。在这种情况下,如果不需要,就不需要公开ToolbarTheme的内部。

  // 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)
  ));

我也遇到了同样的问题,我做了以下修改,问题得到了解决。

打开watchQueryOptions.d.ts文件

\apollo-client\core\watchQueryOptions.d.ts

将查询类型更改为any而不是DocumentNode,与突变相同

之前:

export interface QueryBaseOptions<TVariables = OperationVariables> {
    query: **DocumentNode**;

后:

export interface QueryBaseOptions<TVariables = OperationVariables> {
    query: **any**;

更新

正如@Simon_Weaver的回答中提到的,从TypeScript 3.4版本开始,就可以将它断言为const:

let fruit = "Banana" as const;

旧的答案

你需要转换它:

export type Fruit = "Orange" | "Apple" | "Banana";
let myString: string = "Banana";

let myFruit: Fruit = myString as Fruit;

还要注意,当使用字符串字面量时,您只需要使用一个|

我知道这有点过时了,但这里可能有更好的解决方案。

当需要字符串,但希望字符串只匹配某些值时,可以使用enum。

例如:

enum Fruit {
    Orange = "Orange",
    Apple  = "Apple",
    Banana = "Banana"
}

let myFruit: Fruit = Fruit.Banana;

现在您将知道,无论如何,myFruit将始终是字符串“Banana”(或您选择的任何其他可枚举值)。这对很多事情都很有用,无论是将类似的值分组,还是将用户友好的值映射到机器友好的值,同时强制和限制编译器允许的值。

在扩散的数组中,这个错误仍然会被抛出:

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