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

أنواع Template Literal في TypeScript: الصياغة والأمثلة

أنواع template literal تبني أنواعًا حرفية نصية بصياغة علامات backtick نفسها المستخدمة في قوالب النصوص في JavaScript: on${Capitalize<E>}. تعرّف على الصياغة، وكيف تتضاعف أعضاء union، وUppercase وCapitalize، وأنماطًا مثل ${number}px، وgetters عبر mapped types، وتحليل النصوص بـ infer.

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

نوع template literal يبني أنواعًا حرفية نصية بصياغة علامات backtick نفسها المستخدمة في قوالب النصوص في JavaScript. فالنوع `on${Capitalize<"click" | "focus">}` هو "onClick" | "onFocus"، ويحسبه المترجم:

أنواع template literal موجودة وقت الترجمة فقط. تفحص الأنواع الحرفية النصية والقيم ذات الأنواع المعروفة أثناء كتابة الكود، ولا تضيف شيئًا إلى مخرجات JavaScript. يستخدم جدول المعالجات أعلاه Record ليشترط دالة واحدة لكل اسم.

الصياغة

داخل علامات backtick تكتب نصًا حرفيًا وعناصر نائبة ${...}. يحمل العنصر النائب نوعًا لا قيمة: نوعًا حرفيًا من string أو number أو bigint أو boolean، أو union منها، أو أحد الأنواع الواسعة string وnumber وbigint وboolean وnull وundefined.

العنصر النائب ذو النوع الواسع مثل string أو number يصنع نمطًا: يبقى النوع `hello ${string}` ويُقبل أي نص يطابقه. أما العنصر النائب ذو union المحدود، مثل boolean، فيُوسَّع إلى أعضائه.

أعضاء union تتضاعف

مع عدة unions تكون النتيجة كل التركيبات:

ثلاثة أحجام في درجتين لونيتين تعطي ستة أعضاء. ويكبر العدد بسرعة: خمسة عناصر نائبة يحمل كل منها union من عشرة أحرف تعطي 100,000 عضو، وترفض TypeScript ذلك بالخطأ error TS2590: Expression produces a union type that is too complex to represent. استخدم عنصرًا نائبًا واسعًا مثل ${string} عندما لا تحتاج إلى كل قيمة بعينها.

Uppercase وLowercase وCapitalize وUncapitalize

أربعة أنواع مدمجة تغيّر حالة الأحرف في الأنواع الحرفية النصية. إنها أنواع جوهرية (intrinsic): منفذة داخل المترجم، وليست مكتوبة بـ TypeScript.

النوعالمُدخلالنتيجة
Uppercase<S>"hello world""HELLO WORLD"
Lowercase<S>"Content-Type""content-type"
Capitalize<S>"hello world""Hello world"
Uncapitalize<S>"UserName""userName"

إنها تغيّر الأنواع فقط. لبناء النص المقابل وقت التشغيل ما زلت تستدعي toUpperCase() أو تقتطع النص وتكبّر الحرف الأول بنفسك، ثم تخبر TypeScript أن للنتيجة النوع الدقيق:

الـ as ضروري لأن نوع القيمة المُعادة من toUpperCase() هو string العادي. توقيع الدالة هو ما يراه المستدعون، لذا فلـ capitalize("report") النوع الحرفي "Report".

أنماط النصوص: ${number}px وأخواتها

يقبل نوع النمط كل نص له شكل معيّن. وهو مفيد لقيم CSS والمعرّفات والمفاتيح ذات البادئة المعروفة:

يقبل ${number} أي نص تقرؤه JavaScript كرقم، وهذا أوسع مما يبدو: "-3px" و"1e3px" و"0x10px" كلها تجتاز فحص الأنواع. تعامل مع هذه الأنماط كحماية من الأخطاء الإملائية في القيم الحرفية، لا كتحقق كامل.

أنواع template literal مع mapped types

أنواع template literal أكثر فائدة في جملة as من mapped type، حيث تولّد أسماء خصائص من أسماء خصائص أخرى:

يُبقي string & K المفاتيح النصية فقط، لأن Capitalize لا يقبل الأرقام ولا الرموز (symbols). وتأخذ كل دالة رد نداء نوع معاملها من الخاصية التي تراقبها.

تحليل النصوص بـ infer

في النوع الشرطي، يمكن لـ template literal أن يطابق نصًا ويلتقط أجزاء منه بـ infer. هذا المثال يستخرج أسماء المعاملات من نمط مسار:

احذف postId من الاستدعاء وسيبلّغ المترجم أنه مفقود.

تعبيرات القوالب تتوسع إلى string

تعبير قالب النص في الكود العادي نوعه string، حتى عندما يكون كل جزء منه نوعًا حرفيًا. أضف as const لتحتفظ بنوع template literal:

بدون as const يفشل إسناد loose إلى `log:${Level}`، لأن string قد يكون أي شيء.

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

ما هي أنواع template literal في TypeScript؟

أنواع حرفية نصية تُكتب بعلامات backtick وعناصر نائبة ${...}، مثل قوالب النصوص في JavaScript لكن على مستوى الأنواع. النوع type Greeting = `hello ${string}` يقبل أي نص يبدأ بـ hello ، و`on${Capitalize<"click">}` هو النوع الحرفي "onClick".

ماذا يحدث عندما تضع union داخل نوع template literal؟

يُوسَّع القالب لكل عضو، ومع عدة unions تحصل على كل التركيبات. فـ `${"sm" | "lg"}-${"red" | "blue"}` هو "sm-red" | "sm-blue" | "lg-red" | "lg-blue". أما التركيبات الكبيرة جدًا فتفشل بالخطأ TS2590.

ماذا تفعل Uppercase وLowercase وCapitalize وUncapitalize؟

هي أنواع مدمجة تحوّل الأنواع الحرفية النصية: Uppercase<"id"> هو "ID"، وLowercase<"ID"> هو "id"، وCapitalize<"name"> هو "Name"، وUncapitalize<"Name"> هو "name". إنها تغيّر الأنواع فقط؛ ولتغيير نص وقت التشغيل ما زلت تستدعي toUpperCase() وما يشبهها.

هل تتحقق أنواع template literal من النصوص وقت التشغيل؟

لا. مثل كل أنواع TypeScript تُحذف عند الترجمة، فهي لا تفحص إلا الأنواع الحرفية النصية والقيم ذات الأنواع المعروفة وقت الترجمة. النص الذي يصل وقت التشغيل، من JSON أو من إدخال المستخدم، يبقى مجرد string حتى تفحصه بكودك.

لماذا نوع قالب النص عندي string بدلًا من نوع حرفي؟

تعبير قالب مثل `on${event}` يُوسَّع إلى string عند إسناده إلى متغير. أضف as const (`on${event}` as const) أو صرّح بالنوع الهدف، فتحتفظ TypeScript بنوع template literal، مثل "onclick" | "onfocus".

Coddy programming languages illustration

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

ابدأ الآن