دروس الوحدة (2/2)
النقابات والتضييق
في العالم الحقيقي، لا تحتوي المتغيرات واستجابات واجهة برمجة التطبيقات (API) دائمًا على نوع واحد ثابت. تقدم TypeScript Union Types للتعامل مع التباين، وType Narrowing للعمل عليها بأمان في وقت التشغيل.
أنواع الاتحاد
يسمح نوع الاتحاد للمتغير بقبول قيم من أنواع مختلفة. ويتم التعبير عنها باستخدام رمز الشريط العمودي (|):
let result: number | string;
result = 42; // Valid
result = 'Error 404'; // Validومع ذلك، عند العمل مع نوع موحد، لا يمكننا استدعاء الأساليب التي تنتمي إلى نوع واحد فقط من الأنواع مباشرة (على سبيل المثال، لا يمكننا استدعاء .toUpperCase() إذا كان المتغير يمكن أيضًا أن يكون number). يجب علينا أولا "تضييق" النوع.
اكتب تضييق
تضييق النوع هي العملية التي يقوم فيها TypeScript بتحليل هياكل تدفق التحكم (مثل if أو switch) لاستنتاج نوع أكثر تحديدًا لمتغير في وقت التشغيل.
هناك عدة طرق لإجراء التضييق:
1. المشغل typeof
مثالية للتمييز بين الأنواع البدائية:
function printLength(value: string | number) {
if (typeof value === 'string') {
// TypeScript knows 'value' is a string here
console.log(value.length);
} else {
// TypeScript knows 'value' is a number here
console.log(value.toFixed(2));
}
}2. المشغل in
يستخدم للتحقق من وجود خاصية معينة على كائن:
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
function move(animal: Fish | Bird) {
if ('swim' in animal) {
animal.swim(); // Narrowing to Fish
} else {
animal.fly(); // Narrowing to Bird
}
}النقابات التمييزية
يتكون نمط الاتحادات التمييزية من إنشاء كائنات تشترك في خاصية مشتركة ذات قيمة حرفية فريدة (تسمى discriminator). يتعرف TypeScript على هذا التمييز ويقوم تلقائيًا بتضييق نطاق الكتابة داخل الكتل الشرطية.
interface SuccessResponse {
status: 'success'; // Literal discriminator
data: string;
}
interface ErrorResponse {
status: 'error'; // Literal discriminator
errorMessage: string;
}
type ApiResponse = SuccessResponse | ErrorResponse;
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
console.log('Data received:', response.data);
} else {
console.error('An error occurred:', response.errorMessage);
}
}جربه بنفسك
التمرين 1: أنواع الاتحاد
قم بتعريف متغير يسمى id والذي يمكن أن يكون رقمًا أو سلسلة. قم بتهيئته أولاً بالرقم 101، ثم قم بتعيين قيمة السلسلة "USER-101".
إظهار التلميح
استخدم | عامل لربط الرقم والسلسلة في إعلان المتغير Let.
الحل متاح بعد 3 من المحاولات
التمرين 2: تضييق النوع الأساسي
قم بإنشاء وظيفة باسم formatInput تقبل إدخال معلمة من النوع سلسلة أو رقم. إذا كان الإدخال عبارة عن سلسلة، فسيتم إرجاع الإدخال المحول إلى أحرف كبيرة. إذا كان رقمًا، فقم بإرجاع الإدخال مضروبًا في 2. وحدد الأنواع بشكل صريح.
إظهار التلميح
استخدم typeof input === 'string' داخل كتلة if لتفرع السلوك.
الحل متاح بعد 3 من المحاولات
التمرين 3: التضييق باستخدام "in"
بالنظر إلى الواجهتين Car (مع طريقة القيادة) والقارب (مع طريقة الشراع)، اكتب دالة باسم moveVehicle تقبل مركبة معلمة من النوع Car أو Boat. إذا كانت السيارة تحتوي على خاصية محرك الأقراص، فقم بتنفيذ طريقة محرك الأقراص (). بخلاف ذلك، قم بتنفيذ طريقة الشراع ().
إظهار التلميح
استخدم عامل التشغيل in في النموذج "drive" في السيارة لتضييق الواجهة.
الحل متاح بعد 3 من المحاولات
التمرين 4: شكل الاتحاد التمييزي
تحديد نوع الشكل وهو اتحاد نوعين: الدائرة والمربع. تحتوي الدائرة على خاصية لطيفة تم تعيينها على "دائرة" (القيمة الحرفية) ونصف القطر (رقم). يحتوي Square على خاصية نوع تم تعيينها على "مربع" (القيمة الحرفية) وجانب (رقم). ثم اكتب دالة getArea تقبل الشكل من النوع Shape وترجع المنطقة كرقم (للدائرة Math.PI * radius * radius، للجانب المربع * الجانب).
إظهار التلميح
استخدم Shape.kind === 'circle' داخل getArea لتمييز النوع وحساب المنطقة الصحيحة.
الحل متاح بعد 3 من المحاولات