カスタムタイプがあります。
export type Fruit = "Apple" | "banana" | "grape";
文字列がFruitタイプの一部であるかどうかを判断したいと思います。どうすればこれを達成できますか?
以下は機能しません。
let myfruit = "pear";
if (typeof myfruit === "Fruit") {
console.log("My fruit is of type 'Fruit'");
}
どんな考えでも感謝します!
特にtypeof
演算子に関連するため、TypeScriptの値と型の違いについて混乱する場合があります。お気づきかもしれませんが、TypeScriptは静的な型システムをJavaScriptに追加し、 コードが変換されるとその型システムが消去されます 。 TypeScriptの構文では、一部の式とステートメントは実行時に存在するvaluesを参照し、他の式とステートメントはtypesは、設計時またはコンパイル時にのみ存在します。値は型を持っていますが型ですが、型そのものではありません。重要なのは、コンパイラーが値を予期し、可能であれば値として検出した式を解釈するコードの場所と、コンパイラーが型を予期し、可能であれば式を検出した式を解釈する他の場所があります。
typeof
演算子は二重の寿命をもたらします。式typeof x
は常にx
が値であることを期待しますが、typeof x
自体はコンテキストに応じて値またはタイプになります。
let bar = {a: 0};
let TypeofBar = typeof bar; // the value "object"
type TypeofBar = typeof bar; // the type {a: number}
行let TypeofBar = typeof bar;
はJavaScriptに到達し、実行時に JavaScript typeof演算子 を使用して文字列を生成します。しかし、type TypeofBar = typeof bar
;消去され、 TypeScript type query operator を使用して、TypeScriptがbar
という名前の値に割り当てた静的型を調べています。
あなたのコードでは、
let myfruit = "pear";
if (typeof myfruit === "Fruit") { // "string" === "Fruit" ?!
console.log("My fruit is of type 'Fruit'");
}
typeof myfruit
は値であり、タイプではありません。したがって、TypeScript型のクエリ演算子ではなく、JavaScript typeof
演算子です。常に値"string"
を返します。 Fruit
または"Fruit"
になることはありません。型システムは実行時に消去されるため、実行時にTypeScript型クエリ演算子の結果を取得することはできません。 typeof
演算子をあきらめる必要があります。
あなたがcanすることは、3つの既知のmyfruit
文字列リテラルに対してFruit
の値をチェックすることです... 、 この:
let myfruit = "pear";
if (myfruit === "Apple" || myfruit === "banana" || myfruit === "grape") {
console.log("My fruit is of type 'Fruit'");
}
完璧ですねさて、多分冗長なコードのように思えるかもしれません。冗長性の少ない方法を次に示します。まず、既存のリテラル値の配列に関してFruit
型を定義します... TypeScriptは値から型を推測できますが、型から値を生成することはできません。
const stringLitArray = <L extends string>(arr: L[]) => arr;
const fruit = stringLitArray(["Apple", "banana", "grape"]);
export type Fruit = (typeof fruit)[number];
Fruit
が自分で手動で定義したものと同じタイプであることを確認できます。次に、タイプテストでは、次のように ser-defined type guard を使用できます。
const isFruit = (x: any): x is Fruit => fruit.includes(x);
isFruit()
は、その引数がfruit
配列で見つかったかどうかを確認する関数であり、見つかった場合、その引数の型をFruit
に絞り込みます。動作を見てみましょう:
let myfruit = "pear";
if (isFruit(myfruit)) {
console.log("My fruit is of type 'Fruit'");
}
また、そのタイプガードにより、コンパイラはif
ステートメントの「then」節内で、myfruit
がFruit
であることを認識できます。 Fruit
のみを受け入れる関数と、Fruit
である場合とそうでない場合がある値があるとします。
declare function acceptFruit(f: Fruit): void;
const myfruit = Math.random() < 0.5 ? "pear" : "banana";
関数を直接呼び出すことはできません。
acceptFruit(myfruit); // error, myfruit might be "pear"
ただし、canは、チェック後に "then"句内で呼び出すことができます。
if (isFruit(myfruit)) {
acceptFruit(myfruit); // okay, myfruit is known to be "banana"
}
そもそも、カスタムタイプをチェックしたいのはこのためでしょう。だからそれを行うことができます。
要約すると、typeof
は使用できません。文字列と比較できます。型推論と型ガードを実行して、重複したコードを削除し、コンパイラーから制御フロー型分析を取得できます。
それが役に立てば幸いです。幸運を。