ما هو تضييق النوع (Narrowing)؟
عند التعامل مع اتحاد أنواع، نحتاج معرفة النوع الفعلي قبل استخدامه. حُرّاس الأنواع تساعد TypeScript على تضييق النوع داخل كتلة معيّنة.
الحارس typeof
للأنواع البدائية (string, number, boolean):
function format(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase(); // TypeScript يعرف أنه string
}
return value.toFixed(2); // وهنا number
}
الحارس instanceof
للأصناف والكائنات:
class Dog { bark() {} }
class Cat { meow() {} }
function speak(animal: Dog | Cat) {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
الحارس in
لفحص وجود خاصية في كائن:
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim();
} else {
animal.fly();
}
}
الحُرّاس المخصّصة (Type Predicates)
دالة تُرجع param is Type لتعليم TypeScript بالنوع:
interface User { name: string; }
function isUser(obj: unknown): obj is User {
return typeof obj === "object" && obj !== null && "name" in obj;
}
const data: unknown = { name: "علي" };
if (isUser(data)) {
console.log(data.name); // آمن — TypeScript يعرف أنه User
}
تضييق بالقيمة (Discriminated Unions)
نمط قويّ: حقل مشترك يميّز كل نوع:
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle":
return Math.PI * s.radius ** 2;
case "square":
return s.side ** 2;
}
}
أخطاء شائعة
- استخدام
asللتأكيد القسري بدل حارس نوع آمن. - نسيان فحص
nullضمنtypeof obj === "object"(لأنtypeof nullهو"object").
🎯 التالي: الأنواع المتقدّمة — الشرطية والمُعيَّنة.