الأنواع القابلة للقيمة Null ('strictNull')
جزء من قسم مقدمة إلى TypeScript في رحلة JavaScript على Coddy. الدرس 71 من 73.
بشكل افتراضي، يسمح TypeScript بتعيين null و undefined لأي نوع، مما قد يؤدي إلى أخطاء وقت التشغيل. يغير خيار المترجم strictNullChecks هذا السلوك بجعل null و undefined أنواعاً مستقلة بحد ذاتها.
عندما يتم تمكين strictNullChecks، يجب عليك تضمين null أو undefined بشكل صريح في تعليقات النوع (type annotations) الخاصة بك إذا كنت تريد السماح بهذه القيم:
// Without strictNullChecks - this would be allowed
// بدون strictNullChecks - سيكون هذا مسموحاً
let name: string = null; // Error with strictNullChecks! // خطأ مع strictNullChecks!
// With strictNullChecks - you must be explicit
// مع strictNullChecks - يجب أن تكون صريحاً
let name: string | null = null; // Now this works // الآن هذا يعملهذا يجبرك على التعامل مع قيم null المحتملة قبل استخدامها. لا يمكنك استدعاء الدوال (methods) أو الوصول إلى الخصائص (properties) في قيمة قد تكون null دون التحقق أولاً:
function processName(name: string | null) {
// سيؤدي هذا إلى حدوث خطأ
// console.log(name.toUpperCase());
// يجب عليك التحقق أولاً
if (name !== null) {
console.log(name.toUpperCase()); // آمن للاستخدام
}
}يساعد خيار المترجم (compiler option) هذا في منع أخطاء وقت التشغيل الشائعة "Cannot read property of null" من خلال اكتشافها في وقت التجميع، مما يجعل الكود الخاص بك أكثر موثوقية وقابلية للتنبؤ.
التحدي
سهلقم بإنشاء دالة تعالج بيانات ملف تعريف المستخدم التي قد تحتوي على قيم null بشكل آمن. يوضح هذا التحدي كيف تجبرك خاصية strictNullChecks على التعامل مع الأنواع القابلة للإلغاء (nullable types) بشكل صريح.
قم بإنشاء دالة باسم getUserDisplayName تقوم بما يلي:
- تأخذ معاملًا باسم
fullNameمن نوعstring | null - تعيد الاسم الكامل إذا لم يكن
null - تعيد
"Anonymous User"إذا كان الاسم الكاملnull - تملك نوع إرجاع صريح هو
string
قم بإنشاء دالة ثانية باسم formatUserEmail تقوم بما يلي:
- تأخذ معاملًا باسم
emailمن نوعstring | null - تعيد البريد الإلكتروني بأحرف صغيرة (lowercase) إذا لم يكن
null - تعيد
"No email provided"إذا كان البريد الإلكترونيnull - تملك نوع إرجاع صريح هو
string
قم بإنشاء دالة ثالثة باسم getUserInfo تقوم بما يلي:
- تأخذ معاملين:
nameمن نوعstring | nullوemailمن نوعstring | null - تستخدم كلتا الدالتين السابقتين لمعالجة المعاملات
- تعيد سلسلة نصية منسقة:
"Name: [processed name], Email: [processed email]" - تملك نوع إرجاع صريح هو
string
اختبر دوالك باستخدام البيانات التالية:
- استدعِ
getUserDisplayName("John Smith")واطبع النتيجة - استدعِ
getUserDisplayName(null)واطبع النتيجة - استدعِ
formatUserEmail("ALICE@EXAMPLE.COM")واطبع النتيجة - استدعِ
formatUserEmail(null)واطبع النتيجة - استدعِ
getUserInfo("Bob Johnson", "bob@test.com")واطبع النتيجة - استدعِ
getUserInfo(null, null)واطبع النتيجة - استدعِ
getUserInfo("Sarah Wilson", null)واطبع النتيجة
جرّب بنفسك
// TODO: اكتب كودك هنا
// أنشئ دالة getUserDisplayName التي تأخذ fullName (string | null) وتعيد string
// أنشئ دالة formatUserEmail التي تأخذ email (string | null) وتعيد string
// أنشئ دالة getUserInfo التي تأخذ name و email (كلاهما string | null) وتعيد string
// اختبر الدوال واطبع النتائج
console.log(getUserDisplayName("John Smith"));
console.log(getUserDisplayName(null));
console.log(formatUserEmail("ALICE@EXAMPLE.COM"));
console.log(formatUserEmail(null));
console.log(getUserInfo("Bob Johnson", "bob@test.com"));
console.log(getUserInfo(null, null));
console.log(getUserInfo("Sarah Wilson", null));يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس مقدمة إلى TypeScript
1البداية مع TS
ما هي TypeScript؟لماذا نستخدم TypeScript؟أول كود TypeScript لكعملية الـ Compilation والأخطاءملخص: مقدمة في TS4التعامل مع الدوال
تحديد أنواع المعاملات وقيم الإرجاعتحديد أنواع Arrow Functionsنوع الإرجاع 'void'المعاملات الاختيارية باستخدام '?'القيم الافتراضية للمعاملاتتحديد أنواع Rest Parametersتعريف أنواع الدوالملخص: بناء دوال محددة الأنواع2الأنواع الأساسية
الأنواع الأساسية: str, num, booleanالنوع 'any': مخرج الهروبالنوع 'unknown'التعامل مع 'null' و 'undef'استنتاج الأنواع في التطبيق العمليتوضيحات الأنواع الصريحةمراجعة: تدريب على الأنواع الأساسية5الأنواع: الأسماء المستعارة، الاتحادات والتقاطعات
الأسماء المستعارة للأنواع الأساسية (Primitives)أنواع الاتحاد ('|')التعامل مع أنواع الاتحادالأنواع الحرفية (Literal Types)أنواع التقاطع ('&')دمج الأسماء المستعارة للأنواعملخص: تركيبات الأنواع المتقدمة8Enums
ما هو الـ Numeric Enum؟استخدام الـ Numeric Enumsما هو الـ String Enum؟استخدام الـ String Enumsالـ Heterogeneous Enumsملخص: استخدام الـ Enums11مواضيع متقدمة
تأكيدات النوعحراس النوع: in و instanceofالنوع 'never'الأنواع القابلة للقيمة Null ('strictNull')تواقيع الفهرسة للكائناتملخص: ضبط الأنواع بدقة3هياكل البيانات: المصفوفات و Tuple
المصفوفات محددة النوع (Typed Arrays)معدل 'readonly' للمصفوفاتما هو الـ Tuple؟تعريف والوصول إلى الـ Tuplesتفكيك الـ Tuples (Destructuring)الـ Tuples للقراءة فقط (Readonly)المصفوفات محددة النوع متعددة الأبعاداستخدام Spread Operator مع المصفوفاتملخص: المصفوفات و Tuples6تحديد أنواع الكائنات والواجهات
توصيف أنواع الكائنات المضمنة (Inline)الأسماء المستعارة للأنواع (Type Aliases) للكائناتمقدمة عن الواجهات (Interfaces)الواجهات (Interfaces) مقابل الأسماء المستعارة للأنواع (Type Aliases)الخصائص الاختيارية وخصائص القراءة فقط (Readonly)توسيع الواجهات والأنواعإضافة الدوال (Methods) إلى الواجهاتملخص: تحديد هياكل الكائناتتدرّب بنفسك: Playground لـ TypeScript