الجديد في TypeScript 5.0: Declarators ، و Const Type ، و Enums في التحسين ، والسرعة ، وغير ذلك الكثير!
نشرت: 2023-04-15تم إصدار TypeScript 5.0 رسميًا في 16 مارس 2023 ، وهو الآن متاح للاستخدام للجميع. يقدم هذا الإصدار العديد من الميزات الجديدة بهدف جعل TypeScript أصغر وأبسط وأسرع.
يعمل هذا الإصدار الجديد على تحديث المصممين لتخصيص الفئة ، مما يسمح بتخصيص الفئات وأعضائها بطريقة قابلة لإعادة الاستخدام. يمكن للمطورين الآن إضافة مُعدِّل ثابت إلى إعلان معلمة النوع ، مما يسمح بأن تكون الاستدلالات ذات الشكل الثابت هي الافتراضية. يعمل الإصدار الجديد أيضًا على جعل جميع تعدادات الاتحاد ، وتبسيط بنية التعليمات البرمجية وتسريع تجربة TypeScript.
في هذه المقالة ، سوف تستكشف التغييرات التي تم إدخالها في TypeScript 5.0 ، مما يوفر نظرة متعمقة على ميزاته وإمكانياته الجديدة.
الشروع في العمل مع TypeScript 5.0
TypeScript هو مترجم رسمي يمكنك تثبيته في مشروعك باستخدام npm. إذا كنت تريد البدء في استخدام TypeScript 5.0 في مشروعك ، فيمكنك تشغيل الأمر التالي في دليل مشروعك:
npm install -D typescript
سيؤدي هذا إلى تثبيت المترجم في دليل node_modules ، والذي يمكنك الآن تشغيله باستخدام الأمر npx tsc
.
يمكنك أيضًا العثور على إرشادات حول استخدام الإصدار الأحدث من TypeScript في Visual Studio Code في هذه الوثائق.
ما الجديد في TypeScript 5.0؟
في هذه المقالة ، دعنا نستكشف 5 تحديثات رئيسية تم تقديمها في TypeScript. تشمل هذه الميزات:
مصممون حديثون
كان المصممون موجودون في TypeScript لفترة من الوقت تحت علم تجريبي ، لكن الإصدار الجديد يجعلهم يسارعون مع اقتراح ECMAScript ، والذي هو الآن في المرحلة 3 ، مما يعني أنه في مرحلة حيث تمت إضافته إلى TypeScript.
يعد المصممون وسيلة لتخصيص سلوك الفصول الدراسية وأعضائها بطريقة قابلة لإعادة الاستخدام. على سبيل المثال ، إذا كان لديك فصل دراسي يحتوي على طريقتين ، greet
و getAge
:
class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } greet() { console.log(`Hello, my name is ${this.name}.`); } getAge() { console.log(`I am ${this.age} years old.`); } } const p = new Person('Ron', 30); p.greet(); p.getAge();
في حالات الاستخدام الواقعية ، يجب أن تحتوي هذه الفئة على طرق أكثر تعقيدًا تتعامل مع بعض المنطق غير المتزامن ولها آثار جانبية ، وما إلى ذلك ، حيث قد ترغب في طرح بعض استدعاءات console.log
للمساعدة في تصحيح الأخطاء.
class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } greet() { console.log('LOG: Method Execution Starts.'); console.log(`Hello, my name is ${this.name}.`); console.log('LOG: Method Execution Ends.'); } getAge() { console.log('LOG: Method Execution Starts.'); console.log(`I am ${this.age} years old.`); console.log('Method Execution Ends.'); } } const p = new Person('Ron', 30); p.greet(); p.getAge();
هذا نمط متكرر الحدوث ، وسيكون من الملائم أن يكون لديك حل لتطبيقه على كل طريقة.
هذا هو المكان الذي يلعب فيه المصممون. يمكننا تحديد دالة باسم debugMethod
تظهر على النحو التالي:
function debugMethod(originalMethod: any, context: any) { function replacementMethod(this: any, ...args: any[]) { console.log('Method Execution Starts.'); const result = originalMethod.call(this, ...args); console.log('Method Execution Ends.'); return result; } return replacementMethod; }
في الكود أعلاه ، يأخذ debugMethod
الطريقة الأصلية ( originalMethod
) ويعيد دالة تقوم بما يلي:
- يسجل رسالة "بدء تنفيذ الطريقة".
- يمر بالطريقة الأصلية وجميع الحجج الخاصة بها (بما في ذلك هذا).
- يسجل رسالة "ينتهي تنفيذ الطريقة".
- ترجع أيا كانت الطريقة الأصلية التي تم إرجاعها.
باستخدام أدوات الزخرفة ، يمكنك تطبيق debugMethod
على طرقك كما هو موضح في الكود أدناه:
class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } @debugMethod greet() { console.log(`Hello, my name is ${this.name}.`); } @debugMethod getAge() { console.log(`I am ${this.age} years old.`); } } const p = new Person('Ron', 30); p.greet(); p.getAge();
سينتج هذا ما يلي:
LOG: Entering method. Hello, my name is Ron. LOG: Exiting method. LOG: Entering method. I am 30 years old. LOG: Exiting method.
عند تحديد وظيفة التزيين ( debugMethod
) ، يتم تمرير معلمة ثانية تسمى context
(إنه كائن السياق - يحتوي على بعض المعلومات المفيدة حول كيفية الإعلان عن الطريقة المزخرفة وكذلك اسم الطريقة). يمكنك تحديث debugMethod
للحصول على اسم الطريقة من كائن context
:
function debugMethod( originalMethod: any, context: ClassMethodDecoratorContext ) { const methodName = String(context.name); function replacementMethod(this: any, ...args: any[]) { console.log(`'${methodName}' Execution Starts.`); const result = originalMethod.call(this, ...args); console.log(`'${methodName}' Execution Ends.`); return result; } return replacementMethod; }
عند تشغيل الكود الخاص بك ، سيحمل الإخراج الآن اسم كل طريقة مزينة بمصمم debugMethod
:
'greet' Execution Starts. Hello, my name is Ron. 'greet' Execution Ends. 'getAge' Execution Starts. I am 30 years old. 'getAge' Execution Ends.
هناك المزيد لما يمكنك القيام به مع المصممين. لا تتردد في التحقق من طلب السحب الأصلي للحصول على مزيد من المعلومات حول كيفية استخدام أدوات الديكور في TypeScript.
تقديم معلمات نوع const
هذا إصدار كبير آخر يمنحك أداة جديدة مع الأدوية الجنسية من أجل تحسين الاستدلال الذي تحصل عليه عند استدعاء الوظائف. بشكل افتراضي ، عندما تقوم بتعريف القيم باستخدام const
، فإن TypeScript يستنبط النوع وليس قيمه الحرفية:
// Inferred type: string[] const names = ['John', 'Jake', 'Jack'];
حتى الآن ، لتحقيق الاستدلال المطلوب ، كان عليك استخدام التوكيد الثابت عن طريق إضافة "as const":
// Inferred type: readonly ["John", "Jake", "Jack"] const names = ['John', 'Jake', 'Jack'] as const;
عندما تستدعي الوظائف ، فإنها متشابهة. في الكود أدناه ، نوع البلدان المستنتج هو string[]
:
type HasCountries = { countries: readonly string[] }; function getCountriesExactly(arg: T): T['countries'] { return arg.countries; } // Inferred type: string[] const countries = getCountriesExactly({ countries: ['USA', 'Canada', 'India'] });
قد ترغب في نوع أكثر تحديدًا حيث كانت إحدى طرق الإصلاح السابقة الآن هي إضافة تأكيد as const
:
// Inferred type: readonly ["USA", "Canada", "India"] const names = getNamesExactly({ countries: ['USA', 'Canada', 'India'] } as const);
قد يكون من الصعب تذكر ذلك وتنفيذه. ومع ذلك ، يقدم TypeScript 5.0 ميزة جديدة حيث يمكنك إضافة معدل ثابت إلى إعلان معلمة النوع ، والذي سيطبق تلقائيًا استنتاجًا يشبه الثابت كإعداد افتراضي.
type HasCountries = { countries: readonly string[] }; function getNamesExactly(arg: T): T['countries'] { return arg.countries; } // Inferred type: readonly ["USA", "Canada", "India"] const names = getNamesExactly({ countries: ['USA', 'Canada', 'India'] });
يسمح استخدام معلمات نوع const
للمطورين بالتعبير عن النية بشكل أكثر وضوحًا في التعليمات البرمجية الخاصة بهم. إذا كان المقصود من المتغير أن يكون ثابتًا ولا يتغير أبدًا ، فإن استخدام معلمة من نوع const
يضمن عدم إمكانية تغييره أبدًا عن طريق الخطأ.
يمكنك التحقق من طلب السحب الأصلي للحصول على مزيد من المعلومات حول كيفية عمل معلمة نوع const في TypeScript.
تحسينات على Enums
Enums في TypeScript هي بنية قوية تسمح للمطورين بتعريف مجموعة من الثوابت المسماة. في TypeScript 5.0 ، تم إجراء تحسينات على التعدادات لجعلها أكثر مرونة وفائدة.
على سبيل المثال ، إذا كان لديك التعداد التالي تم تمريره إلى دالة:
enum Color { Red, Green, Blue, } function getColorName(colorLevel: Color) { return colorLevel; } console.log(getColorName(1));
قبل تقديم TypeScript 5.0 ، كان بإمكانك تمرير رقم مستوى خاطئ ، ولن يتسبب في أي خطأ. ولكن مع إدخال TypeScript 5.0 ، فإنه سيؤدي إلى ظهور خطأ على الفور.
أيضًا ، يجعل الإصدار الجديد جميع التعدادات في تعدادات نقابية عن طريق إنشاء نوع فريد لكل عضو محسوب. يسمح هذا التحسين بتضييق جميع التعدادات والإشارة إلى أعضائها كأنواع:
enum Color { Red, Purple, Orange, Green, Blue, Black, White, } type PrimaryColor = Color.Red | Color.Green | Color.Blue; function isPrimaryColor(c: Color): c is PrimaryColor { return c === Color.Red || c === Color.Green || c === Color.Blue; } console.log(isPrimaryColor(Color.White)); // Outputs: false console.log(isPrimaryColor(Color.Red)); // Outputs: true
تحسينات أداء TypeScript 5.0
يتضمن TypeScript 5.0 العديد من التغييرات المهمة في بنية التعليمات البرمجية ، وهياكل البيانات ، والامتدادات الحسابية. ساعد هذا في تحسين تجربة TypeScript بأكملها ، من التثبيت إلى التنفيذ ، مما يجعلها أسرع وأكثر كفاءة.
على سبيل المثال ، الفرق بين حجم حزمة TypeScript 5.0 و 4.9 مثير للإعجاب.
تم ترحيل TypeScript مؤخرًا من مساحات الأسماء إلى الوحدات النمطية ، مما يسمح لها بالاستفادة من أدوات البناء الحديثة التي يمكنها إجراء تحسينات مثل رفع النطاق. أيضًا ، أدت إزالة بعض التعليمات البرمجية المهملة إلى إزالة حوالي 26.4 ميجابايت من حجم حزمة TypeScript 4.9 والذي يبلغ 63.8 ميجابايت.
فيما يلي بعض الانتصارات الأكثر إثارة في السرعة والحجم بين TypeScript 5.0 و 4.9:
سيناريو | الوقت أو الحجم المرتبط بـ TS 4.9 |
بناء الوقت المادي لواجهة المستخدم | 90٪ |
وقت بدء تشغيل برنامج التحويل البرمجي TypeScript | 89٪ |
بناء الوقت للكاتب المسرحي | 88٪ |
وقت الإنشاء الذاتي لمحول TypeScript | 87٪ |
Outlook Web وقت الإنشاء | 82٪ |
وقت بناء VS Code | 80٪ |
حجم حزمة الطباعة npm | 59٪ |
دقة الحزمة للحصول على حل أفضل للوحدة النمطية
عندما تكتب جملة استيراد في TypeScript ، يحتاج المترجم إلى معرفة ما يشير إليه الاستيراد. يقوم بذلك باستخدام دقة الوحدة النمطية. على سبيل المثال ، عندما تكتب import { a } from "moduleA"
، يحتاج المترجم إلى معرفة تعريف a
moduleA
" للتحقق من استخدامها.
في TypeScript 4.7 ، تمت إضافة خيارين جديدين للإعدادات --module
و moduleResolution
: node16
و nodenext
.
كان الغرض من هذه الخيارات هو تمثيل قواعد البحث الدقيقة لوحدات ECMAScript في Node.js. ومع ذلك ، يحتوي هذا الوضع على العديد من القيود التي لا يتم فرضها بواسطة أدوات أخرى.
على سبيل المثال ، في وحدة ECMAScript في Node.js ، يجب أن يتضمن أي استيراد نسبي امتداد ملف لكي يعمل بشكل صحيح:
import * as utils from "./utils"; // Wrong import * as utils from "./utils.mjs"; // Correct
أدخلت TypeScript إستراتيجية جديدة تسمى "moduleResolution bundler". يمكن تنفيذ هذه الإستراتيجية عن طريق إضافة الكود التالي في قسم “compilerOptions” من ملف تكوين TypeScript:
{ "compilerOptions": { "target": "esnext", "moduleResolution": "bundler" } }
هذه الإستراتيجية الجديدة مناسبة لأولئك الذين يستخدمون الحزم الحديثة مثل Vite و esbuild و swc و Webpack و Parcel وغيرهم ممن يستخدمون إستراتيجية بحث مختلطة.
يمكنك التحقق من طلب السحب الأصلي وتنفيذه لمزيد من المعلومات حول كيفية عمل moduleResolution
bundler في TypeScript.
الإستنكار
يأتي TypeScript 5.0 مع بعض الإهلاك ، بما في ذلك متطلبات وقت التشغيل وتغييرات lib.d.ts وتغييرات كسر واجهة برمجة التطبيقات.
- متطلبات وقت التشغيل: يستهدف TypeScript الآن ECMAScript 2018 ، وتحدد الحزمة الحد الأدنى لتوقع المحرك عند 12.20. لذلك ، يجب أن يكون لدى مستخدمي Node.js إصدار 12.20 كحد أدنى أو أحدث لاستخدام TypeScript 5.0.
- تغييرات lib.d.ts: كانت هناك بعض التغييرات على كيفية إنشاء أنواع لـ DOM ، والتي قد تؤثر على الكود الحالي. على وجه الخصوص ، تم تحويل خصائص معينة من عدد إلى أنواع حرفية رقمية ، وتم نقل خصائص وطرق معالجة الأحداث للقص والنسخ واللصق عبر الواجهات.
- تغييرات كسر واجهة برمجة التطبيقات (API): تمت إزالة بعض الواجهات غير الضرورية ، وتم إجراء بعض تحسينات التصحيح. تم نقل TypeScript 5.0 أيضًا إلى الوحدات النمطية.
قام TypeScript 5.0 بإهمال بعض الإعدادات والقيم المقابلة لها ، بما في ذلك target: ES3
، out
، noImplicitUseStrict
، keyofStringsOnly
، suppressExcessPropertyErrors
، suppressImplicitAnyIndexErrors
، noStrictGenericChecks
، charset
، importsNotUsedAsValues
wellports، and preserveValueImports
.
بينما ستظل هذه التكوينات صالحة حتى TypeScript 5.5 ، سيتم إصدار تحذير لتنبيه المستخدمين الذين لا يزالون يستخدمونها.
ملخص
في هذه المقالة ، تعلمت بعض الميزات والتحسينات الرئيسية التي يقدمها TypeScript 5.0 ، مثل التحسينات التي تم إجراؤها على التعدادات ودقة الحزمة ومعلمات نوع const ، إلى جانب تحسينات السرعة والحجم.
إذا كنت تفكر في TypeScript لمشاريعك القادمة ، فامنح Kinsta Application Hosting تجربة مجانية.
الان حان دورك! ما هي الميزات أو التحسينات التي تجدها أكثر جاذبية في TypeScript 5.0؟ هل هناك أي أشياء مهمة ربما أغفلناها؟ اسمحوا لنا أن نعرف في التعليقات.