انمذج حالات تطبيقك باتحادات يتحقق منها المترجم نيابة عنك.
افتح هذا الدرس في Kodokonيقيّد النوع الحرفي القيمة إلى محتوى محدد بدقة: 'info' بدل string. إنه أساس واجهات 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. هذه الآلية، المسماة narrowing، تحل محل الفحوص اليدوية الهشة. أضف حارس الشمولية لتُحكم إغلاق المنظومة كلها.
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);
}
}