TypeScriptの網羅性チェック
下記に示しているのは自作の関数 exhaustiveCheck
を毎度呼ぶものだが、これの記述自体をなくせる
「「チェック漏れ」漏れ」をなくせる
Union型に対して網羅性チェックをする
以下のように書くと、例えば case 'C'
が抜けているときにエラーを出してくれる
tsconst hoge = (v: 'A' | 'B' | 'C') => {
switch (v) {
case 'A':
return;
case 'B':
return;
case 'C':
return;
default:
const _: never = v;
}
};
正しいときも '_' is declared but its value is never read.
が出るので以下のような関数を用意しておくとよい
tsexport const exhaustiveCheck = (x: never): never => {
throw new Error(`Unexpected object: ${x}`);
};
上のコードをこう書き換える
tsdefault:
return exhaustiveCheck(v);
ヘルパー関数を使わない例
ts throw new Error(`Unknown type: ${(action as { type: "__invalid__" }).type}`);
ts new Error(`${action satisfies never}`)
ReduxのReducerで使用する場合
しかし、これをreduxのreducerのswitch文で同じようなことするとエラーになる
何故なら、自分で定義したAction型とは別に @@redux/INIT${randomString()}
のようなActionが投げ込まれるため、実行時にdefault節に入り、Errorがthrowされる
exhaustiveCheck関数とは別に、reducer用の漏れチェック関数を用意すると良い
tsexport const endReducer = <T>(state: T, _action: never): T => {
return state;
};
tsfunction reducer(...) ..
switch (action.type) {
...
default:
return endReducer(state, action);
}
}