توثيق النوع هو ميزة سينتاكيدية مثيرة في TypeScript. بينما تظهر في نفس المكان كتعليمات النوع المعادلة للمجموعات البارزة، تبدو أكثر مثل جملة مبنية صريحة من التعليمات العامة. وهذا يعطيك سيطرة أكبر على التحكم في التفقد النوعي.
مع إصدار TypeScript 5.5، أصبح التعامل بالتوثيق النوعي أكثر فهما حاليًا لأنه يتم تخمينه تلقائيًا في أسباب عديدة. لكن إذا كنت تتنقل خلال أقدم أساسات البرمجيات قليلًا، فإنك من المحتمل أن تصطدم بالتوثيق النوعي المكتوب بيدًا أكثر عادة.
في هذه المقالة، سنقوم بالبحث بسرعة في ما هو التوثيق النوعي ولماذا يمكن الاستفادة منه. دعونا نبدأ بالنظر إلى المشكل الذي يحله التوثيق النوعي.
المشكل
أعتقد أن أفضل طريقة لفهم أهمية التوثيق النوعي هي من ملاحظة المشاكل التي تأتي عندما لا نملكها:
function isString(value: unknown): boolean {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string | number
}
return " ".repeat(padding) + input; // Opps type error here
// ^
// string | number
}
في هذه المثالية، يُعيد نوع المعونة لـ isString
إلى boolean
ونستخدمه في ما يطلق عليه ما يسمى padLeft
لإضافة تكوينات إلى اليسار لعبارة المدخل. الـ padding
يمكن أن يكون عبارة معينة أو عدد معين من أحرف المسافر.
أنت قد تتساءل لماذا قمت بتعيين النوع المرجعي إلى boolean
. هذا لإظهار الخلل. إذا لم تضيف أي تعيين لنوع الإرجاع وتستخدم أحدث إصدار من TypeScript، فلن تلاحظ أي مشكلة هنا. الآن، تحمل معي – سنناقش الاختلافات المتصلة بالإصدار قريبا.
سيعمل الدالة بشكل سلس بدون التشغيل، ولكن TypeScript لا يمكن أن تنفذ أي تحجيم النوع مع isString
. وكنتيجة لذلك، نوع padding
يظل string | number
كلا في داخل وخارج الجملة if
. هذا يؤدي إلى تعارض مع ما تتوقعه repeat
من نوع معاملته الأولى، مما يسبب الخطأ النوعي.
الحل: دخول الصفات النوعية
حتى لو كنت غير مألوف بالمصطلح المحكم، ربما قمت باستخدامهم من قبل. الصفات في البرمجة هي ببساطة دوال تعيد قيمة من نوع الـ boolean لإجابة سؤال نعم/لا. عدة وظائف مبنية في جافاسكريبت العناصر، مثل filter
، find
، every
، و some
، تستخدم الصفات المحكمة لمساعدة في القرار.
صفات النوع هي طريقة لجعل الصفات المحكمة أكثر فائدة لتحجيم النوع. يمكننا إصلاح الخلل باستخدام صفة النوع كنوع الإرجاع:
function isString(value: unknown): value is string {
return typeof value === "string";
}
هنا الصفة النوعية هي value is string
. إنه يقول ثلاثة أشياء:
-
إن الدالة صفة. لذلك ستظهر TypeScript خطأ إذا حاولت إرجاع أي شيء غير قيمة من نوع Boolean.
-
إذا عاملت
true
, فإنvalue
من النوع النادر -
إذا عاملت
false
, فإنvalue
ليس من النوعstring
.
يمكنك بواسطة المقاييس التصنيفية إنشاء حراس نوع المعلومات. وهي فحوصات منطقية تسمح لك بتحديد الأنواع المتفتحة إلى أنواع أكثر تعقيدًا، أي تنحنيها. إذًا، يعتبر الوظيفة العاملة أيضًا حراس نوع المعلومات المعروف بالقيم.
هذا هو البرمجيات بأكملها:
function isString(value: unknown): value is string {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string
}
return " ".repeat(padding) + input;
// ^
// number
}
في هذه الحالة، تقوم TypeScript بتنحني نوع padding
داخل العبارة الشرطية if
وخارجها.
الآن دعونا ننظر بسرعة إلى كيف عملت المقاييس التصنيفية قبل TypeScript 5.5 وما أحسنت هذه الإصدارة.
مقاييس التصنيف التي عملت قبل TypeScript 5.5
في مثالنا السابق، إذا لم نحدد أي نوع من الإعادة، فإنه سيتم تخمينه كboolean
:
function isString(value: unknown) {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string | number
}
return " ".repeat(padding) + input; // Opps type error here
// ^
// string | number
}
بدت الخطأ نفسه عندما كتبنا نوع الإرجاع يدويًا boolean
. هنا رابط ملعب TypeScript للشريحة البرمجية أعلاه. انتقل وألق نظرة على الوظائف أو المتغيرات لإحساس أفضل بالأنواع. ومن ثم انظر كيف يحل المعيار النوعي المشكلة.
إذا لم نحدد المعيار النوعي، ستؤدي استخدام تقنيات كـ filter
أيضًا إلى اكتشاف نوع خاطئ:
function isString(value: unknown) {
return typeof value === "string";
}
const numsOrStrings = [1, 'hello', 2, 'world'];
// ^
// strings: (string | number)[]
const strings = numsOrStrings.filter(isString);
// ^
// strings: (string | number)[]
الآن دعونا نرى كيف يحسن TypeScript 5.5 الوضع.
معيارات النوع بعد TypeScript 5.5
أحد الميزات الرئيسية لـ TypeScript 5.5 هو قدرته على استنتاج المعيارات النوعية بتحليل جسم الوظيفة. لذلك إذا كنت تستخدم TypeScript 5.5 أو أحدث، فلا يتوجب عليك كتابة المعيار النوعي كنوع الإرجاع لـ isString
. يفعل TypeScript ذلك لك، والكود كما ترونه في العينة أدناه يعمل بشكل ممتاز:
function isString(value: unknown) {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// سلسلة
}
return " ".repeat(padding) + input; // خطأ في النوع هنا
// ^
// عدد
}
const numsOrStrings = [1, 'hello', 2, 'world'];
const strings = numsOrStrings.filter(isString);
// ^
// السلاسل: string[]
const numbers = numsOrStrings.filter((v) => !isString(v));
// ^
// الأرقم: number[]
لم أجد بعد حالة حيث لا أكون راضيًا عن الاستدلال التلقائي للنوع. إذا وجدت واحدة، يمكنك دائمًا كتابتها يدويًا.
مزيد من الدراسة
في هذه المقالة، استكشفنا بإيجاز استدلالات النوع في TypeScript. إذا كنت مهتمًا بمعرفة المزيد وفهم الحالات الحدودية، فإليك الأدلة الرسمية:
شكرا لقراءتك! سترانا في المرة القادمة!
خلفية الصورة الجلدية من Mona Eendra على Unsplash
Source:
https://www.freecodecamp.org/news/what-are-type-predicates-in-typescript/