अपने application की states को उन unions से मॉडल करें जिन्हें compiler आपकी ओर से जाँचता है।
इस पाठ को Kodokon में खोलेंएक literal type किसी value को सटीक content तक सीमित कर देता है: string के बजाय 'info'। यह उन APIs की नींव है जिनका ग़लत इस्तेमाल असंभव है: compiler सूची के बाहर की किसी भी value को अस्वीकार कर देता है, और आपका editor autocompletion देता है।
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अगला कदम है ऐसे object types को मिलाना जो एक साझा literal property साझा करते हैं, जिसे discriminant कहते हैं। किसी network call की हर state, उदाहरण के लिए, केवल वही data रखती है जो उससे संबंधित है: loading के दौरान 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 type को narrow कर देता है: case 'error' के बाद, state.message मौजूद है और state.data नहीं। यह तंत्र, जिसे narrowing कहते हैं, नाज़ुक manual जाँचों की जगह ले लेता है। पूरे चीज़ को बंद करने के लिए एक exhaustiveness guard जोड़ें।
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);
}
}