تحديد أنواع مفاتيح الترجمة
اشتقوا اتحاد المفاتيح الصالحة من ملفات الرسائل
تحديد أنواع مفاتيح الترجمة درس مجاني في TypeScript Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في TypeScript Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة TypeScript Academy 4 دروس في المجموع.
اشتقاق مفاتيح الترجمة الصالحة
في إعداد i18n آمن الأنواع، تُشتق مجموعة مفاتيح الترجمة الصالحة من كائن الرسائل. ويصبح خطأ مطبعي مثل t("greetng") خطأً في الترجمة، بدلًا من أن يكون خطأ سلسلة مفقودة وقت التشغيل.
كائن الرسائل
ابدؤوا بكائن عادي من الرسائل. فهو المصدر الوحيد للحقيقة لكل من القيم ونوع المفاتيح.
const messages = {
greeting: "Hello",
farewell: "Goodbye",
cart: {
empty: "Your cart is empty",
checkout: "Proceed to checkout",
},
} as const;المفاتيح العليا باستخدام keyof
بالنسبة إلى كائن مسطح، تمنحكم keyof typeof اتحاد المفاتيح.
type TopKeys = keyof typeof messages;
// "greeting" | "farewell" | "cart"مشكلة التداخل
تكون فهارس الرسائل الفعلية متداخلة. ونريد مسارات مفصولة بنقاط مثل "cart.empty"، لا المفاتيح العليا فقط. لذلك نحتاج إلى نوع递ursive يمر عبر الكائن.
نوع مسار递ursive
يبني نوع شرطي + نوع مُحوّل مسارات مفصولة بنقاط عبر التكرار داخل الكائنات المتداخلة وإضافة بادئات إلى المفاتيح. وتستخدم البادئة نوعًا حرفيًا قالبًا، ويُكتب في الشيفرة الفعلية باستخدام backticks بالشكل [backtick]${K}.${Paths<T[K]>}[backtick]. نعرضه أدناه باسم JoinPath(K, child) للحفاظ على نظافة القائمة.
type JoinPath<K extends string, Rest extends string> = K + "." + Rest;
// (Real TS uses a template literal type:
// the K dot Rest pattern delimited by backticks.)
type Paths<T> = {
[K in keyof T & string]: T[K] extends string
? K
: K | (T[K] extends object
? JoinPath<K, Paths<T[K]>>
: never);
}[keyof T & string];تطبيقه
يؤدي تمرير نوع الرسائل إلى Paths إلى الحصول على كل مفتاح مفصول بنقاط صالح.
type MsgKey = Paths<typeof messages>;
// "greeting" | "farewell" | "cart" | "cart.empty" | "cart.checkout"مفاتيح الأوراق فقط
غالبًا ما تريدون مسارات الأوراق فقط، أي السلاسل الفعلية، مع استبعاد الكائنات الوسيطة. عدّلوا التكرار لتخطي العقد غير النصية. وتستخدم بادئة K-dot-child مرة أخرى نوعًا حرفيًا قالبًا، محددًا بـ backticks في الشيفرة الفعلية، ونمثلها هنا باسم JoinPath.
type LeafPaths<T> = T extends string
? ""
: {
[K in keyof T & string]: T[K] extends string
? K
: JoinPath<K, LeafPaths<T[K]>>;
}[keyof T & string];
// "greeting" | "farewell" | "cart.empty" | "cart.checkout"دالة t منمّطة
قيّدوا معلمة دالة الترجمة باتحاد المفاتيح المشتق، حتى لا تُترجم إلا المفاتيح الصالحة.
declare function t(key: LeafPaths<typeof messages>): string;
t("cart.empty"); // ok
t("cart.missing"); // Error: not a valid keyحل نوع القيمة
يمكنكم التقدم خطوة أخرى واستنتاج نوع القيمة عند مسار معين، وهو أمر مفيد عندما تتضمن الرسائل إدخالات غير نصية. ويمر نوع شرطي لفهرسة المسار عبر النقاط. إذ يقسم المسار باستخدام نمط حرفي قالب، يُكتب في الشيفرة الفعلية باستخدام backticks على هيئة Head dot Rest مع infer. ونمثل هذا التقسيم أدناه باسم SplitHead/SplitRest.
// Conceptually: split "cart.empty" into Head="cart", Rest="empty"
// using a template literal pattern with infer.
type ValueAt<T, P extends string> =
P extends SplitHead<infer Head, infer Rest>
? Head extends keyof T ? ValueAt<T[Head], Rest> : never
: P extends keyof T ? T[P] : never;لماذا يهم as const
من دون as const، تتسع القيم النصية إلى string، وتفقدون المعلومات الحرفية اللازمة لاحقًا، مثل استخراج العناصر النائبة. أعلنوا الفهارس دائمًا باستخدام const.
لماذا يهم ذلك
يعني اشتقاق المفاتيح من الفهرس أن إضافة رسالة أو إعادة تسميتها أو حذفها يحدّث فورًا نوع المفتاح المسموح به في كل موضع. فلا حاجة إلى تعداد مركزي للصيانة، ولا إلى ثوابت نصية قديمة.
اختبار سريع
تأكدوا من فهمكم لتنميط مفاتيح الترجمة.
مراجعة
اشتققتم اتحادًا من المفاتيح الصالحة من كائن messages باستخدام keyof إلى جانب نوع مسار递ursive حرفي قالب. وتستبعد الصيغ التي تقتصر على الأوراق الكائنات الوسيطة، كما ترفض دالة t المنمّطة المفاتيح غير الصالحة، ويحافظ as const على المعلومات الحرفية التي تحتاج إليها آلية الأنواع.
الأسئلة الشائعة
هل درس «تحديد أنواع مفاتيح الترجمة» مجاني؟
نعم — نص درس «تحديد أنواع مفاتيح الترجمة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة TypeScript Academy، انتقل إلى CoddyKit PRO. تتضمن دورة TypeScript Academy 4 دروس في المجموع.
ماذا ستتعلم في «تحديد أنواع مفاتيح الترجمة»؟
اشتقوا اتحاد المفاتيح الصالحة من ملفات الرسائل تتمرن على TypeScript Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ TypeScript Academy؟
لا تُشترط خبرة سابقة. TypeScript Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «تحديد أنواع مفاتيح الترجمة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس TypeScript Academy هذا؟
نعم. كل درس في TypeScript Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تحديد أنواع مفاتيح الترجمة
- أمان أنواع الاستيفاء
- التصريف الجمعي مع الأنواع
- استنتاج الأنواع المدرك للإعدادات المحلية