以下は、fruit.tsにあるものです。
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;
また、 string literals を使用する場合は、|
を1つだけ使用する必要があることに注意してください。
これを行うとき:
export type Fruit = "Orange" | "Apple" | "Banana"
...リテラル"Orange"
、"Apple"
、および"Banana"
のみを含むことができるFruit
という型を作成しています。この型はString
を拡張するため、String
に割り当てることができます。ただし、String
は"Orange" | "Apple" | "Banana"
を拡張しないため、それに割り当てることはできません。 String
はより具体的ではないです。 任意の文字列にできます。
これを行うとき:
export type Fruit = "Orange" | "Apple" | "Banana"
const myString = "Banana";
const myFruit: Fruit = myString;
...できます。どうして?この例のmyString
の実際のtypeは"Banana"
であるためです。はい、"Banana"
はtypeです。 String
を拡張しているため、String
に割り当てることができます。さらに、タイプextendsは、コンポーネントのanyを拡張するときのUnion Typeこの場合、タイプの"Banana"
は、そのコンポーネントの1つを拡張するため、"Orange" | "Apple" | "Banana"
を拡張します。したがって、"Banana"
は"Orange" | "Apple" | "Banana"
またはFruit
に割り当てることができます。
これは少し古いと思いますが、より良い解決策があるかもしれません。
文字列が必要であるが、特定の値にのみ一致させる場合は、 enums を使用できます。
例えば:
enum Fruit {
Orange = "Orange",
Apple = "Apple",
Banana = "Banana"
}
let myFruit: Fruit = Fruit.Banana;
これで、myFruitが常に文字列 "Banana"(または選択したその他の列挙可能な値)になることがわかります。これは、コンパイラが許可する値を強制および制限しながら、このような類似の値をグループ化するか、ユーザーフレンドリーな値をマシンフレンドリーな値にマッピングするかなど、多くのことに役立ちます。
TypeScript 3.4
は新しい「const」アサーションを導入します
いわゆるstring
アサーションを使用して、リテラル型('orange'
または'red'
など)がconst
を入力するように「拡大」されるのを防ぐことができます。
次のことができるようになります。
let fruit = <const> 'orange';
そして、それ自体はstring
になりません-これは問題のエラーの根本です。
この特定のエラーが発生する状況はいくつかあります。 OPの場合、値文字列として明示的に定義されたがありました。そのため、これはドロップダウン、またはWebサービスまたは生のJSON文字列から来たのではないかと推測する必要があります。
その場合、単純なキャスト<Fruit> fruitString
またはfruitString as Fruit
が唯一の解決策です(他の回答を参照)。コンパイル時にこれを改善することはできません。
ただし、コードで定数を使用するときに、同じエラーに遭遇するのは非常に簡単ですこれまで文字列型にするつもりはなかった。私の答えは、2番目のシナリオに焦点を当てています。
まず第一に:「マジック」文字列定数が列挙型よりも優れているのはなぜですか
幸いなことに以下を定義するとき:
export type FieldErrorType = 'none' | 'missing' | 'invalid'
...実際に定義しているのはnion of typesここで'missing'
は実際には型です!
TypeScriptとコンパイラに'banana'
のような文字列があると、「割り当て不可」エラーに遭遇することがよくありますthinks私はそれを文字列として意図していましたが、実際には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 = {field:FieldName、error:FieldError};
これでエラーが発生したとしましょう(文字列ではない割り当て可能なエラー):
fieldErrors: [ { field: 'number', error: 'invalid' } ]
次のように、オブジェクト全体をFieldErrorType
として「アサート」できます。
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
その後、<'invalid'> 'invalid'
を行う必要がなくなります。
しかし、タイプミスはどうですか? <FieldErrorType>
は、そのタイプになる権利があるものは何でもassertしません。この場合ではありません-幸いにも、コンパイラWILLこれを行うと文句を言います。
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
たとえば、データをモックするときにdropdownvalue[]
にキャストする場合は、値と表示プロパティを持つオブジェクトの配列として作成します。
例:
[{'value': 'test1', 'display1': 'test display'},{'value': 'test2', 'display': 'test display2'},]
私は同じ問題に直面していたので、以下の変更を行い、問題は解決しました。
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**;