여기 내가 과일에 가지고있는 것이 있습니다.
export type Fruit = "Orange" | "Apple" | "Banana"
이제 다른 typescript 파일로 fruit.ts를 가져오고 있습니다. 여기 내가 가진 것
myString:string = "Banana";
myFruit:Fruit = myString;
내가 할 때
myFruit = myString;
오류가 발생합니다.
‘string’유형은 ‘ “Orange”유형에 지정할 수 없습니다. | “애플”| “바나나”‘
사용자 정의 유형 Fruit 변수에 문자열을 할당하려면 어떻게해야합니까?
답변
당신은 그것을 캐스팅해야합니다 :
export type Fruit = "Orange" | "Apple" | "Banana";
let myString: string = "Banana";
let myFruit: Fruit = myString as Fruit;
또한 문자열 리터럴 을 사용할 때는 하나만 사용해야합니다.|
편집하다
@Simon_Weaver의 다른 답변에서 언급했듯이 이제는 다음과 같이 주장 할 수 있습니다 const
.
let fruit = "Banana" as const;
답변
Typescript 3.4
는 새로운 ‘const’주장을 소개합니다
이제 리터럴 유형 (예 : 'orange'
또는 'red'
)이 string
소위 const
주장 으로 입력하기 위해 ‘확대’되는 것을 방지 할 수 있습니다 .
당신은 할 수있을 것입니다 :
let fruit = 'orange' as const; // or...
let fruit = <const> 'orange';
그리고 그것은 string
더 이상 그 자체로 변하지 않을 것입니다 -이것이 문제의 근본 원인입니다.
답변
이렇게하면 :
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"
는 IS 유형 . 확장 가능 String
하여에 할당 할 수 String
있습니다. 또한 유형 은 구성 요소를 확장 할 때 결합 유형을 확장 합니다 . 이 경우 "Banana"
유형 "Orange" | "Apple" | "Banana"
은 구성 요소 중 하나를 확장 하므로 확장됩니다. 따라서 또는에 "Banana"
할당 할 수 있습니다."Orange" | "Apple" | "Banana"
Fruit
답변
나는 이것이 조금 오래된 것을 보았지만 여기에 더 나은 해결책이있을 수 있습니다.
문자열을 원하지만 문자열이 특정 값과 만 일치하도록하려면 enums 를 사용할 수 있습니다 .
예를 들면 다음과 같습니다.
enum Fruit {
Orange = "Orange",
Apple = "Apple",
Banana = "Banana"
}
let myFruit: Fruit = Fruit.Banana;
이제 무엇이든 myFruit은 항상 문자열 “Banana”(또는 열거 가능한 다른 값)가 될 것입니다. 이것은 컴파일러가 허용하는 값을 적용하고 제한하면서 이와 유사한 값을 그룹화하거나 사용자 친화적 인 값을 기계 친화적 인 값으로 매핑하는 등 많은 것들에 유용합니다.
답변
이 특정 오류를 발생시키는 몇 가지 상황이 있습니다. OP의 경우 명시 적으로 문자열로 정의 된 값이있었습니다 . 따라서 이것은 드롭 다운 또는 웹 서비스 또는 원시 JSON 문자열에서 비롯된 것으로 가정해야합니다.
이 경우 간단한 캐스트 <Fruit> fruitString
또는 fruitString as Fruit
유일한 해결책입니다 (다른 답변 참조). 컴파일 타임에는 이것을 향상시킬 수 없습니다. [ 편집 :에 대한 다른 답변보기<const>
]!
그러나 코드에서 문자열 유형이 아닌 상수를 사용할 때이 동일한 오류가 발생하기 쉽습니다 . 내 대답은 두 번째 시나리오에 중점을 둡니다.
우선 : 왜 ‘매직’문자열 상수가 종종 열거 형보다 낫습니까?
- 나는 문자열 상수가 열거 형과 열거 형을 좋아합니다-컴팩트하고 ‘자바 스크립트’
- 사용중인 구성 요소가 이미 문자열 상수를 사용하는 경우 더 의미가 있습니다.
- 열거 형 값을 얻기 위해 ‘enum type’을 가져와야하는 것은 그 자체로 까다로울 수 있습니다
- 내가 무엇을하든 컴파일 안전 하기를 원하므로 공용체 유형에서 유효한 값을 제거하거나 잘못 입력하면 컴파일 오류가 발생해야합니다.
다행히도 다음을 정의 할 때
export type FieldErrorType = 'none' | 'missing' | 'invalid'
… 당신은 실제로 정의하고 유형의 조합'missing'
실제로 타입입니다!
필자는 'banana'
typescript와 같은 문자열이 있고 컴파일러 가 문자열을 의미 한다고 생각 하는 경우 ‘할당 할 수 없음’오류가 종종 발생 하지만 실제로는 유형이되기를 원했습니다 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!
왜? 이것은 typescript이므로 <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 = {필드 : FieldName, 오류 : FieldError};
이 오류가 발생한다고 가정합니다 (할당 할 수없는 문자열).
fieldErrors: [ { field: 'number', error: 'invalid' } ]
전체 객체를 다음 FieldErrorType
과 같이 ‘어설 션’할 수 있습니다 .
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
그렇다면 우리는 할 필요가 없습니다 <'invalid'> 'invalid'
.
그러나 오타는 어떻습니까? 하지 않습니다 <FieldErrorType>
단지 주장 유형이 될 수있는 권리에 무엇이든. 이 경우에는 아닙니다. 다행스럽게도 컴파일러 는 불가능하다는 것을 알기에 충분히 영리하기 때문에 이렇게하면 불평 할 것입니다 .
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
답변
위의 모든 대답은 유효하지만 문자열 리터럴 유형이 다른 복잡한 유형의 일부인 경우가 있습니다. 다음 예제를 고려하십시오.
// 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 매개 변수를 자체적으로 사용해야하는 경우에 좋습니다. 예를 들어, 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 내부를 노출 할 필요가 없습니다.
// 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)
));
답변
dropdownvalue[]
예를 들어 데이터를 조롱 할 때에 캐스팅하는 경우 값 및 표시 속성이있는 객체의 배열로 데이터를 작성하십시오.
예 :
[{'value': 'test1', 'display1': 'test display'},{'value': 'test2', 'display': 'test display2'},]
