この特定のエラーが発生する状況はいくつかあります。OPの場合、文字列として明示的に定義された値がありました。そのため、ドロップダウン、Webサービス、または未加工のJSON文字列が原因であると想定する必要があります。
その場合には、単純なキャスト<Fruit> fruitString
やfruitString as Fruit
(他の回答を参照してください)唯一のソリューションです。コンパイル時にこれを改善することはできません。[ 編集:私の他の回答を参照してください<const>
]!
ただし、string型であることが意図されていないコードで定数を使用すると、この同じエラーが発生するのは非常に簡単です。私の答えは、その2番目のシナリオに焦点を当てています。
まず第一に、なぜ「魔法の」文字列定数はしばしば列挙型よりも優れているのですか?
- 文字列定数の外観と列挙型の違い-コンパクトで「javascripty」
- 使用しているコンポーネントがすでに文字列定数を使用している場合、より意味があります。
- 列挙値を取得するためだけに「列挙型」をインポートする必要があることは、それ自体が面倒な場合があります
- 私が何をしてもそれをコンパイルセーフにしたいので、追加してユニオンタイプから有効な値を削除したり、タイプミスしたりすると、コンパイルエラーが発生するはずです。
幸いにも次のように定義すると:
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!
どうして?これは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};
これでエラーが発生したとしましょう(文字列not assignableエラー):
fieldErrors: [ { field: 'number', error: 'invalid' } ]
オブジェクト全体を次のFieldErrorType
ように「アサート」できます。
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
その後、私たちはやらなければならないことを避けます<'invalid'> 'invalid'
。
しかし、タイプミスはどうですか?そのタイプであることの右側にあるものを主張する<FieldErrorType>
だけではありません。このケースではない-幸いコンパイラはWILLあなたがこれを行う場合、それはそれは不可能だ知っている賢い十分なので、文句を言います:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
export type Fruit
か?