Nullable في TypeScript: كيفية تعريف نوع يمكن أن يكون null؟

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

TypeScript وسؤاله الأبدي: كيف تجعل النوع nullable؟

\n\n

مرحبًا، زميلي! إذا كنت قد كتبت يومًا ما بلغة TypeScript، فبالتأكيد واجهت موقفًا حيث قد ترجع الدالة قيمة، وقد لا ترجع. أو متغير لا تتم تهيئته فورًا. وهنا يطرح السؤال الجوهري: كيف تعلن عن نوع يمكن أن يكون null أو undefined؟

\n\n

هذا السؤال هو من أكثر الأسئلة شيوعًا على Stack Overflow (عشرات الآلاف من المشاهدات!)، وليس بدون سبب. TypeScript صارم ولكنه عادل. لا يسمح لنا ببساطة بتعيين null لمتغير من النوع string. وهذا رائع لأنه ينقذنا من الكثير من الأخطاء. ولكن ماذا تفعل عندما يكون nullable جزءًا من منطق العمل؟ دعنا نفهم ذلك.

\n\n

في هذه المقالة، لن نقدم إجابة جافة فقط. سننتقل من الأساسيات إلى التقنيات المتقدمة، ونحلل الأخطاء الشائعة، ونتعلم كيفية كتابة كود آمن وأنيق. هيا بنا!

\n\n

الأساسيات: Union Types و Null

\n\n

أبسط وأكثر طريقة مباشرة لجعل النوع nullable هي استخدام union type (اتحاد الأنواع). إذا كان المتغير يمكن أن يكون سلسلة نصية أو null، نكتب هكذا:

\n\n
let userName: string | null = null;\nuserName = "أليس"; // صحيح\nuserName = null;    // صحيح أيضًا\n
\n\n

نفس الشيء ينطبق على undefined. في TypeScript، null و undefined هما نوعان مختلفان (إذا لم يتم تفعيل العلم --strictNullChecks، ولكن سنتحدث عنه لاحقًا).

\n\n
let age: number | undefined;\nage = 25;\nage = undefined; // يعمل\n
\n\n

مهم: إذا كنت تستخدم | null أو | undefined، فإن TypeScript سيجبرك على التحقق من القيمة قبل الاستخدام. محاولة استدعاء دالة على كائن قد يكون null ستؤدي إلى خطأ في الترجمة. هذه هي "السلامة" التي نحبها في TS.

\n\n

مثال من الحياة الواقعية: البحث عن مستخدم

\n\n
interface User {\n  id: number;\n  name: string;\n}\n\nfunction findUser(id: number): User | null {\n  // ...منطق البحث\n  if (id === 1) {\n    return { id: 1, name: "إيفان" };\n  }\n  return null;\n}\n\nconst user = findUser(2);\n// user.name; // خطأ! 'user' قد يكون null\nif (user) {\n  console.log(user.name); // الآن آمن\n}\n
\n\n

أترى؟ المترجم نفسه يخبرك: "تحقق، وإلا ستسقط!". هذا يوفر ساعات من التصحيح.

\n\n

المعلمات والخصائص الاختيارية (Optional Chaining)

\n\n

غالبًا ما تكون nullable ليست فقط المتغيرات، بل أيضًا حقول الكائنات أو وسائط الدوال. لهذا، يوجد في TypeScript صيغة خاصة — optional modifier (علامة الاستفهام ?).

\n\n

المعلمات الاختيارية للدوال

\n\n
function greet(name?: string) {\n  if (name) {\n    return `مرحبًا، ${name}!`;\n  }\n  return "مرحبًا، أيها الغريب!";\n}\n\nconsole.log(greet("بيتيا")); // مرحبًا، بيتيا!\nconsole.log(greet());       // مرحبًا، أيها الغريب!\n
\n\n

نوع المعامل name يصبح تلقائيًا string | undefined. لاحظ: إذا كان المعامل اختياريًا، يمكنك عدم تمريره، ولن يشتكي TS.

\n\n

الخصائص الاختيارية في الواجهات

\n\n
interface Config {\n  url: string;\n  port?: number; // يمكن أن يكون number أو undefined\n}\n\nconst config1: Config = { url: "http://localhost" }; // port غير موجود\nconst config2: Config = { url: "http://localhost", port: 3000 };\n
\n\n

عند الوصول إلى config1.port، سيقول TypeScript إنه number | undefined. وهذا صحيح — لا نعرف ما إذا كان المنفذ محددًا.

\n\n

السلسلة الاختيارية (Optional Chaining) — أفضل صديق لك

\n\n

مع ظهور ES2020 و TypeScript 3.7، لدينا طريقة أنيقة للوصول بأمان إلى الخصائص المتداخلة التي قد تكون null أو undefined. وهذا يسمى optional chaining

المدونات

توصيات الكتب