[解決済み] TypeScriptでswitchブロックが網羅的であることを確認する方法とは?
2022-05-14 17:12:04
質問
私はいくつかのコードを持っています。
enum Color {
Red,
Green,
Blue
}
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
// Forgot about Blue
}
throw new Error('Did not expect to be here');
}
を処理するのを忘れていました。
Color.Blue
のケースを処理するのを忘れていて、コンパイルエラーが出た方がよかったと思います。TypeScriptがこれをエラーとしてフラグを立てるようにするには、どのようにコードを構成すればよいでしょうか?
どのように解決するのですか?
これを実現するために
never
型(TypeScript 2.0で導入)を使用します。これは、"not" が発生してはならない値を表します。
まず最初に関数を書きます。
function assertUnreachable(x: never): never {
throw new Error("Didn't expect to get here");
}
そして、それを
default
の場合(あるいは同等に、スイッチの外側で)。
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
}
return assertUnreachable(c);
}
この時点で、エラーが表示されます。
return assertUnreachable(c);
~~~~~~~~~~~~~~~~~~~~~
Type "Color.Blue" is not assignable to type "never"
エラーメッセージは、網羅的なスイッチに入れ忘れたケースを示します! もし複数の値を入れ忘れた場合は、例えば
Color.Blue | Color.Yellow
.
もし、あなたが
strictNullChecks
を使っている場合、その
return
の前にある
assertUnreachable
を呼び出します (それ以外は任意)。
お望みであれば、もう少し凝ったこともできます。たとえば、判別済み和集合を使用している場合、デバッグのためにアサーション関数で判別プロパティを回復すると便利なことがあります。それは次のようなものです。
// Discriminated union using string literals
interface Dog {
species: "canine";
woof: string;
}
interface Cat {
species: "feline";
meow: string;
}
interface Fish {
species: "pisces";
meow: string;
}
type Pet = Dog | Cat | Fish;
// Externally-visible signature
function throwBadPet(p: never): never;
// Implementation signature
function throwBadPet(p: Pet) {
throw new Error('Unknown pet kind: ' + p.species);
}
function meetPet(p: Pet) {
switch(p.species) {
case "canine":
console.log("Who's a good boy? " + p.woof);
break;
case "feline":
console.log("Pretty kitty: " + p.meow);
break;
default:
// Argument of type 'Fish' not assignable to 'never'
throwBadPet(p);
}
}
これは良いパターンです。なぜなら、期待されるすべてのケースを処理したことを確認するために、コンパイル時の安全性が得られるからです。また、本当にスコープ外のプロパティ(例えば、JSの呼び出し元が新しい
species
を作ったJS呼び出し元がある)、有用なエラーメッセージを投げることができる。
関連
-
[解決済み] TypeScriptで文字列を数値に変換する方法とは?
-
[解決済み] TypeScript で `window` に新しいプロパティを明示的に設定するにはどうすればよいですか?
-
[解決済み] TypeScriptでオブジェクトに動的にプロパティを割り当てるには?
-
[解決済み] TypeScriptで配列の項目を削除するには?
-
[解決済み] JSONオブジェクトをTypeScriptのクラスにキャストする方法を教えてください。
-
[解決済み] TypeScriptで文字列をenumに変換するには?
-
[解決済み] Typescript によるインターフェース型チェック
-
[解決済み] TypeScriptで配列に文字列が含まれているかどうかを確認するには?
-
[解決済み] TypeScriptのクラス型チェック
-
[解決済み】Typescriptで、文字列がNumericであるかどうかを確認する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Typescriptで、! (エクスクラメーションマーク/バン)演算子でメンバを再参照するのは?
-
[解決済み] Typescript ReferenceError: exports が定義されていません。
-
[解決済み] TypeScriptでグローバル変数を作成する
-
[解決済み] TypeScriptでオブジェクトを初期化する方法
-
[解決済み] TypeScriptの "*.d.ts "について
-
[解決済み] Typescript オブジェクトのインデックス付きメンバの型を強制する?
-
[解決済み] String型とstring型の違いは何ですか?
-
[解決済み] タイプスクリプトのレコードタイプとは何ですか?
-
[解決済み】「エラー TS2533: オブジェクトは 'null' または 'undefined' の可能性があります」を抑制する方法とは?
-
[解決済み】tsconfig.jsonファイルを生成するにはどうしたらいいですか?