コンパイラが代わりにチェックしてくれるユニオンで、アプリケーションの状態をモデル化しましょう。
このレッスンを Kodokon で開くリテラル型は値を厳密な内容に制限します。string ではなく 'info' です。誤用しようがない API の土台となるもので、コンパイラはリスト外のあらゆる値を拒否し、エディタは自動補完を提供してくれます。
type Level = "info" | "warn" | "error";
function log(level: Level, message: string): void {
console.log(`[${level}] ${message}`);
}
log("info", "Server started");
// log("fatal", "Boom"); -> rejected by the compiler次のステップは、共通のリテラルプロパティ(判別子と呼ばれます)を共有するオブジェクト型を組み合わせることです。たとえばネットワーク呼び出しの各状態は、それ自身に属するデータだけを持ちます。読み込み中に data へアクセスすることは、そもそも不可能なのです。
type ApiState =
| { status: "loading" }
| { status: "success"; data: string[] }
| { status: "error"; message: string };
function render(state: ApiState): string {
switch (state.status) {
case "loading":
return "Loading...";
case "success":
return state.data.join(", ");
case "error":
return state.message;
}
}各 case の中で、TypeScript は型を絞り込みます。case 'error' のあとでは state.message が存在し、state.data は存在しません。ナローイングと呼ばれるこの仕組みは、壊れやすい手動チェックに取って代わります。網羅性ガードを加えて、全体をしっかり固めましょう。
function assertNever(value: never): never {
throw new Error("Unhandled case: " + String(value));
}
function label(state: ApiState): string {
switch (state.status) {
case "loading": return "In progress";
case "success": return "Done";
case "error": return "Failed";
default: return assertNever(state);
}
}