Menu
flag Ar iconالعربيةdown icon

المعاملات الاختيارية في TypeScript: القيم الافتراضية وrest

اجعل معاملًا اختياريًا في TypeScript بـ ?، أو أعطه قيمة افتراضية، أو اجمع أي عدد من الوسائط بمعامل rest. يغطي قواعد الترتيب، والفرق بين الوسيط المحذوف وundefined، وكائنات الخيارات، والمعاملات الاختيارية في أنواع الدوال.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

أضف ? بعد اسم المعامل لجعله اختياريًا. يمكن للمستدعين تركه، وداخل الدالة يتضمن نوعه undefined.

تفحص TypeScript عدد الوسائط، لذلك دون ? كان الاستدعاء الأول سيكون خطأ ترجمة: Expected 2 arguments, but got 1. (TS2554).

المعاملات الاختيارية قد تكون undefined

لأن المستدعي يستطيع حذفه، يكون نوع المعامل الاختياري داخل الدالة T | undefined. وتحت strictNullChecks يجب أن تعالج حالة undefined قبل استخدامه كـ T.

الأداتان المعتادتان هنا هما optional chaining (?.) وnullish coalescing (??). وعندما تكون القيمة البديلة ثابتة، يكون المعامل الافتراضي أقصر.

القيم الافتراضية للمعاملات

تجعل القيمة الافتراضية المعامل اختياريًا للمستدعين وتعطيه نوعًا بلا undefined داخل الدالة. يُستنتج النوع من القيمة الافتراضية، فكثيرًا ما يكون التعليق غير ضروري.

يرى المستدعي التوقيع repeat(text: string, times?: number, separator?: string). تتبع القيم الافتراضية قاعدة JavaScript: تُطبَّق عندما يكون الوسيط undefined، سواء حُذف أو مُرر صراحة، ولا تُطبَّق عندما يكون null. ويمكن لتعبير القيمة الافتراضية استخدام المعاملات السابقة: function range(start: number, end = start + 10).

قواعد ترتيب المعاملات

التصريحهل يُترجم؟ملاحظات
(a: number, b?: number)نعمالمعاملات الاختيارية تأتي في النهاية
(a?: number, b: number)لاTS1016: A required parameter cannot follow an optional parameter.
(a = 0, b: number)نعملكن يجب أن يكتب المستدعون f(undefined, 5) لاستخدام القيمة الافتراضية
(a: number, ...rest: number[])نعممعامل rest دائمًا في النهاية
(a?: number, ...rest: number[])نعمالاختياري قبل rest مسموح

المعامل ذو القيمة الافتراضية قبل معامل إلزامي قانوني لكنه مزعج. يصبح نوعه عند المستدعين number | undefined، ولا أحد يحب كتابة undefined كعنصر نائب. إذا احتجت إلى معامل أول مرن، فاستخدم كائن خيارات أو تحميل الدوال الزائد بدلًا من ذلك.

المحذوف مقابل undefined

يتشابه x?: number وx: number | undefined ولهما النوع نفسه داخل الدالة. ويختلفان عند المستدعي: الأول يمكن حذفه، والثاني يجب تمريره.

استخدم | undefined لوسيط إلزامي يُسمح بأن يكون بلا قيمة، حتى يضطر كل مستدعٍ إلى التفكير فيه. واستخدم ? عندما يكون تركه استدعاءً عاديًا. (تقول الرسالة فعلًا "1 arguments": هذه صياغة TypeScript.)

معاملات Rest

يجمع معامل rest، ...name: T[]، أي عدد من الوسائط في مصفوفة. يجب أن يكون المعامل الأخير.

نشر مصفوفة في معاملات ثابتة أكثر صرامة. يقبل معامل rest نشر أي number[]، لكن الدالة المعلنة (a: number, b: number) لا تقبل إلا نشر tuple، لأن TypeScript يجب أن تعرف الطول:

function point(x: number, y: number) { return { x, y }; }

const list = [3, 4];            // number[]
point(...list);
// error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.

const pair = [3, 4] as const;   // readonly [3, 4]
point(...pair);                 // fine

يمكن أن يكون لمعامل rest أيضًا نوع tuple، يحدد نوع كل موضع: ...args: [name: string, age?: number].

كائنات الخيارات

عندما يكون لدالة أكثر من معاملين أو ثلاثة اختيارية، يفقد المستدعون تتبع المواضع. كائن خيارات مع قيم افتراضية يعطي وسائط مسماة لا يهم ترتيبها.

يجعل = {} في النهاية الكائن كله اختياريًا. دونه يكون fetchData("/a") خطأ ترجمة (Expected 2 arguments, but got 1.، TS2554)، وفي JavaScript العادية كان الاستدعاء نفسه سيرمي TypeError وقت التشغيل، لأن التفكيك يحتاج إلى كائن يقرأ منه.

المعاملات الاختيارية في أنواع Callbacks

في نوع الدالة، تعني ? «قد لا يمرره مستدعي هذا الـ callback». ولا تعني «قد يتخطاه الـ callback»: يستطيع الـ callback دائمًا تجاهل المعاملات الأخيرة. لذلك لا تعلّم معاملات الـ callback كاختيارية لمجرد السماح للمعالجات بأخذ وسائط أقل.

// Too loose: every handler must now cope with index being undefined
type Visit = (item: string, index?: number) => void;

// Right: the caller always passes both; handlers may use only item
type VisitStrict = (item: string, index: number) => void;
const log: VisitStrict = (item) => console.log(item);

الأسئلة الشائعة

كيف أجعل معاملًا اختياريًا في TypeScript؟

ضع ? بعد اسمه: function greet(name?: string). يمكن للمستدعين تركه، وداخل الدالة يكون نوعه string | undefined، فتفحصه قبل استخدامه. وإعطاء المعامل قيمة افتراضية، name = "there"، يجعله اختياريًا أيضًا ويحذف undefined داخل الدالة.

هل يمكن أن يأتي معامل اختياري قبل معامل إلزامي في TypeScript؟

ليس مع ?: (a?: number, b: number) هو الخطأ TS1016، "A required parameter cannot follow an optional parameter." يمكن أن يأتي معامل ذو قيمة افتراضية أولًا، لكن عندها يجب أن يمرر المستدعون undefined صراحة لاستخدام القيمة الافتراضية، لذلك عمليًا تأتي المعاملات الاختيارية وذات القيم الافتراضية في النهاية.

ما الفرق بين x?: number و x: number | undefined؟

داخل الدالة كلاهما number | undefined. الفرق عند الاستدعاء: مع x?: number يمكن حذف الوسيط، أما مع x: number | undefined فيجب تمريره، حتى لو كانت القيمة undefined. وتركه يعطي الخطأ TS2554.

هل تمرير null يستخدم القيمة الافتراضية للمعامل؟

لا. تطبّق JavaScript القيمة الافتراضية فقط عندما يكون الوسيط undefined (محذوفًا أو ممررًا صراحة). وnull قيمة، فتُحفظ. وترفض TypeScript على أي حال null لمعامل number تحت strictNullChecks.

كيف أمرر مصفوفة كوسائط منفصلة في TypeScript؟

انشرها: fn(...args). لدالة ذات معاملات ثابتة، يجب أن يكون للمصفوفة نوع tuple مثل [number, number] أو أن تأتي من as const؛ فنشر number[] يعطي الخطأ TS2556 لأن طولها غير معروف. أما النشر في معامل rest (...values: number[]) فيعمل دائمًا.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن