sourcecode

형식 스크립트 형식 'string'을 형식에 할당할 수 없습니다.

copyscript 2022. 9. 12. 11:45
반응형

형식 스크립트 형식 'string'을 형식에 할당할 수 없습니다.

이게 내가 가진 과일이야.

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

이제 fruit.ts를 다른 typescript 파일로 Import합니다.여기 내가 가진 게 있어요

myString:string = "Banana";

myFruit:Fruit = myString;

할 때

myFruit = myString;

에러가 표시된다.

'string' 유형은 'Orange' | 'Apple' | 'Banana' 유형에 할당할 수 없습니다.

커스텀 유형의 Fruit 변수에 문자열을 할당하려면 어떻게 해야 합니까?

갱신하다

와 같이 3.4로는 @Simon_Weaver로 수 const:

let fruit = "Banana" as const;

구답

캐스팅은 다음과 같습니다.

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

let myFruit: Fruit = myString as Fruit;

또한 문자열 리터럴을 사용할 때는 1개만 사용해야 합니다.|

타이프스크립트에서는 새로운 'const' 어설션이 도입되었습니다.

이것으로 리터럴 타입(예: 'orange' ★★★★★★★★★★★★★★★★★」'red''타자'로하면 '타자, '타자'로 하면 됩니다.string '일명 '일부러'라고 하는 것을 가지고const★★★★★★ 。

다음을 수행할 수 있습니다.

let fruit = 'orange' as const;  // or...
let fruit = <const> 'orange';

그가 ''가 아니라 '아예'가 되는 string더 이상 - 이것이 질문의 문제의 근본입니다.

오브젝트 전체에서도 실행할 수 있습니다.

let animals = [ { species: 'dog' }, { species: 'cat' } ] as const;

type firstAnimal = (typeof animals)[0]['species'];  // string literal 'dog'

보너스 힌트:<const> false ★★★★★★★★★★★★★★★★★」<const> truetrue 또는 false여야 하는 부울을 나타냅니다.이것은 때때로 차별된 조합에서 유용할 수 있다.보시면 아실 거예요.

이 경우:

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

...라는 유형을 이치노Fruit할 수 ."Orange","Apple" ★★★★★★★★★★★★★★★★★」"Banana"이은 확장형입니다.String에 이렇게 될 수 StringString하지 "Orange" | "Apple" | "Banana"을 사용하다 String구체성이 떨어집니다.임의의 문자열이 될 수 있습니다.

이 경우:

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

const myString = "Banana";

const myFruit: Fruit = myString;

효과가 있어. 왜?왜냐하면 실제 타입은myString에서는 " " 입니다."Banana" 그렇습니다"Banana"타입입니다.연장되어 있다String할당이 가능하기 때문에String또, 타입은 컴포넌트를 확장할 때 유니언 타입을 확장합니다.이 경우,"Banana"은 확장, 타입은 확장, 타입은 확장, 타입은 확장, 타입은 확장됩니다."Orange" | "Apple" | "Banana"부품 중 하나를 확장하기 때문입니다. 때문에, 「 」는,"Banana"할 수 ."Orange" | "Apple" | "Banana" ★★★★★★★★★★★★★★★★★」Fruit.

이 에러가 발생하는 상황은 몇 가지 있습니다.OP의 경우 문자열로 명시적으로 정의된 값이 있습니다.따라서 이것은 드롭다운 또는 웹 서비스 또는 raw JSON 문자열에서 나온 것이라고 가정해야 합니다.

한 출연자<Fruit> fruitString ★★★★★★★★★★★★★★★★★」fruitString as Fruit유일한 해결책입니다(다른 답변 참조).컴파일 시간에는 이 문제를 개선할 수 없습니다.[편집: 에 대한 다른 답변 보기]!

그러나 코드 내에서 문자열 유형이 아닌 상수를 사용할 경우 이와 같은 오류가 발생하기 쉽습니다.제 대답은 두 번째 시나리오에 초점을 맞추고 있습니다.


우선:'매직' 문자열 상수가 열거형보다 더 좋은 이유는 무엇입니까?

  • 문자열 상수 vs. 열거형 - 콤팩트하고 'javascripty'가 마음에 듭니다.
  • 사용 중인 구성 요소가 이미 문자열 상수를 사용하는 경우 더 적합합니다.
  • 열거값을 얻기 위해 'enum type'을 Import해야 하는 것 자체가 번거로울 수 있습니다.
  • 무엇을 하든 컴파일을 안전하게 하고 싶기 때문에 유니언 타입에서 유효한 값을 삭제하거나 잘못 입력하면 컴파일 오류가 발생합니다.

다행히 다음을 정의할 때:

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' | 'expirationDate', 내보내기 유형 FieldError = 'none' | 'export' | 'export 유형 FieldErrorType = { field:필드 이름, 오류:필드 오류 };

다음과 같은 오류가 발생했다고 가정합니다(문자열을 할당할 수 없습니다).

  fieldErrors: [ { field: 'number', error: 'invalid' } ]

을 '수 .FieldErrorType음음음같 뭇매하다

  fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]

안 될 것 같아요.<'invalid'> 'invalid'.

지만만 오자 ?? ???? 않다.<FieldErrorType>그런 타입이 될 권리가 있다면 무엇이든 주장하세요.이 경우는 아닙니다.다행히 컴파일러가 이 작업을 하면 불평할 것입니다.그것은 불가능하다는 것을 충분히 알고 있기 때문입니다.

  fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]

이게 좀 낡긴 했지만, 더 나은 해결책이 있을지도 몰라요.

문자열이 필요하지만 문자열이 특정 값에만 일치하도록 하려면 enum을 사용할 수 있습니다.

예를 들어 다음과 같습니다.

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

let myFruit: Fruit = Fruit.Banana;

이제 myFruit은 항상 문자열 "Banana"(또는 선택한 다른 열거형 값)임을 알게 됩니다.이는 컴파일러가 허용하는 값을 적용 및 제한하면서 이와 같은 유사한 값을 그룹화하거나 사용자 친화적인 값을 머신 친화적인 값에 매핑하는 경우 등 많은 경우에 유용합니다.

위의 답변은 모두 유효하지만 String Literal Type이 다른 복잡한 유형의 일부일 수 있습니다.다음 예를 생각해 보겠습니다.

  // 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) 첫 번째 해결책은 사이즈의 종류를 정의하고 foo.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) 두 번째 옵션은 타입 툴바에 캐스트하는 것입니다.주제. 이 경우 도구 모음의 내부를 노출할 필요가 없습니다.필요 없는 주제.

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

이 에러가 확산된 어레이에서도, 다음과 같이 약간 오해의 소지가 있습니다.

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

리액트 컴포넌트에 소품을 전달할 때도 비슷한 문제가 있었습니다.

★★★★★★★My type inference on myArray wasn't working correctly

https://codesandbox.io/s/type-string-issue-fixed-z9jth?file=/src/App.tsx

Reactiflux의 Brady가 이 문제를 해결하는데 도움을 준 것에 대해 특별히 감사드립니다.

dropdownvalue[]예를 들어 데이터를 조롱할 때는 값 및 표시 속성을 가진 개체의 배열로 구성합니다.

:

[{'value': 'test1', 'display1': 'test display'},{'value': 'test2', 'display': 'test display2'},]

이 문제는 Angular와 관련이 없는데 Angular로 표기되었습니다.단, 예기치 않게 이 오류가 발생할 수 있는 Angular 고유의 경우가 적어도1개 있습니다.

  • 「」를 디세블로 경우strictNullInputTypes
  • 다음과 같은 리터럴 유형을 사용하는 경우Fruit@Input()
  • 은 .'Orange'문자열로 해석됩니다.

이는 Angular 13.1에서 수정됩니다.

https://github.com/angular/angular/pull/38305

클래스로 작업하는 경우 다음 중 하나를 수행할 수 있습니다.

모델 예:

type Fruit = 'Apple' | 'Banana';

interface ClassWithFruit  {
  fruit: Fruit;
}

모델을 구현하는 클래스에는 다음 세 가지 옵션이 있습니다.

class MyClass implements ClassWithFruit {
  // option 1
  fruit = 'Apple' as const;

  // option 2
  fruit = <const>'Apple';
  
  // option 3
  readonly fruit = 'Apple';
}

저도 같은 문제에 직면하고 있었습니다만, 아래와 같이 변경해, 문제가 해결되었습니다.

watchQueryOptions.d.ts 파일을 엽니다.

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

DocumentNode 대신 쿼리 유형 any를 변경합니다. 변환의 경우 동일합니다.

이전:

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

그 후:

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

언급URL : https://stackoverflow.com/questions/37978528/typescript-type-string-is-not-assignable-to-type

반응형