قبل بضعة أيام ، أعلنا عن توفر مرشح الإصدار (RC) الخاص بنا من TypeScript 3.4. أملنا هو جمع الملاحظات والقضايا المبكرة لضمان سهولة إصدارنا النهائي واستخدامه على الفور.
لبدء استخدام RC ، يمكنك الحصول عليها من خلال NuGet ، أو استخدام npm مع الأمر التالي:
npm install -g typescript@rc
يمكنك أيضًا الحصول على دعم محرر بواسطة
دعنا نستكشف الجديد في 3.4!
هذا المقال في مدونتناأسرع يبني لاحقة مع العلم --incremental
نظرًا لأن ملفات TypeScript يتم تصنيفها ، فإنها تقدم خطوة متوسطة بين كتابة التعليمات البرمجية وتشغيلها. أحد أهدافنا هو تقليل الوقت المبني نظرًا لأي تغيير في البرنامج. طريقة واحدة للقيام بذلك هي عن طريق تشغيل TypeScript في - وضع الساعة. عندما يتغير أحد الملفات في وضع - --watch
، فإن TypeScript يكون قادرًا على استخدام الرسم البياني للتبعية الذي تم إنشاؤه مسبقًا في المشروع لتحديد الملفات التي يحتمل أن تكون قد تأثرت وتحتاج إلى إعادة فحصه وإعادة إرساله المحتمل. هذا يمكن تجنب فحص كامل النوع وإعادة إرسالها والتي يمكن أن تكون مكلفة.
ولكن من غير الواقعي أن نتوقع من جميع المستخدمين الحفاظ على عملية tsc --watch
تعمل بين عشية وضحاها لمجرد الحصول على بنيات أسرع صباح الغد. ماذا عن البرد يبني؟ خلال الأشهر القليلة الماضية ، كنا نعمل لمعرفة ما إذا كانت هناك طريقة لحفظ المعلومات المناسبة من - وضع الساعة إلى ملف واستخدامها من البناء إلى البناء.
يقدم TypeScript 3.4 علامة جديدة تسمى --incremental
والتي تخبر TypeScript بحفظ المعلومات حول الرسم البياني للمشروع من التحويل البرمجي الأخير. في المرة التالية التي يتم فيها استدعاء --incremental
مع - --incremental
، ستستخدم هذه المعلومات للكشف عن الطريقة الأقل تكلفة لفحص التغييرات وإرسالها إلى مشروعك.
بشكل افتراضي مع هذه الإعدادات ، عندما نقوم بتشغيل tsc ، سيبحث TypeScript عن ملف يسمى .tsbuildinfo
في دليل الإخراج الخاص بنا ( ./lib
). إذا كان ./lib/.tsbuildinfo
غير موجود ، فسيتم إنشاؤه. ولكن إذا حدث ذلك ، tsc
استخدام هذا الملف للتحقق تدريجياً من ملفات الإخراج وتحديثها.
يمكن حذف ملفات .tsbuildinfo
هذه بأمان ولا يكون لها أي تأثير على التعليمات البرمجية الخاصة بنا في وقت التشغيل - يتم استخدامها بشكل محض لجعل عمليات التجميع أسرع. يمكننا أيضًا تسمية أي شيء نريده ، ووضعهم في أي مكان نريد باستخدام علامة --tsBuildInfoFile
.
طالما حاول أي شخص آخر الكتابة إلى ملف ذاكرة التخزين المؤقت نفسه ، يجب أن نكون قادرين على التمتع بنيات بارد تزايدي أسرع.
المشاريع المركبة
جزء من الهدف من المشاريع المركبة ( tsconfig.json
s مع مجموعة composite
إلى true
) هو أنه يمكن بناء المراجع بين المشاريع المختلفة بشكل تدريجي. على هذا النحو ، ستنتج المشاريع المركبة دائمًا ملفات .tsbuildinfo
.
outFile
عند استخدام outFile
، سوف يعتمد اسم ملف معلومات البناء على اسم ملف الإخراج. على سبيل المثال ، إذا كان ملف جافا سكريبت الخاص بنا هو ./output/foo.js
، ثم تحت علامة --incremental ، ستقوم TypeScript بإنشاء الملف ./output/foo.tsbuildinfo
. كما ذكر أعلاه ، يمكن التحكم في ذلك --tsBuildInfoFile
علامة --tsBuildInfoFile
.
- تنسيق الملف والإصدار
في حين أن الملف الذي تم إنشاؤه بواسطة --incremental
هو JSON ، فإن الملف لا يعني أن تستهلكه أي أداة أخرى. لا يمكننا توفير أي ضمانات لاستقرار محتوياته ، وفي الواقع ، فإن سياستنا الحالية هي أن أي إصدار واحد من TypeScript لن يفهم ملفات .tsbuildinfo
إنشاؤها من إصدار آخر.
تحسينات لـ ReadonlyArray
و tuples readonly
يجعل TypeScript 3.4 من الأسهل استخدام أنواع تشبه الصفيف للقراءة فقط.
بناء جملة جديد لـ ReadonlyArray
يصف نوع ReadonlyArray
يمكن قراءتها فقط. لا يمكن لأي متغير ذي مؤشر إلى ReadonlyArray
إضافة أو إزالة أو استبدال أي من عناصر الصفيف.
function foo(arr: ReadonlyArray<string>) { arr.slice();
في حين أنه من الممارسات الجيدة في كثير من الأحيان استخدام ReadonlyArray
over Array
لغرض النية ، إلا أنه غالبًا ما يكون الألم نظرًا لأن المصفوفات تحتوي على بناء جملة أجمل. على وجه التحديد ، number[]
هو نسخة مختصرة من Array<number>
، تمامًا مثل Date[]
هو اختصار لـ Array<Date>
.
يقدم TypeScript 3.4 بناء جملة جديد لـ ReadonlyArray
باستخدام معدّل readonly
جديد لأنواع الصفيف.
function foo(arr: readonly string[]) { arr.slice();
tuples readonly
يقدم TypeScript 3.4 أيضًا دعمًا جديدًا للصفوف المقروءة readonly
. يمكننا بادئة أي نوع tuple بالكلمة الرئيسية readonly
لجعلها tuple readonly
، مثلما نستطيع الآن مع بناء جملة مجموعة الاختزال المختصر. كما قد تتوقع ، على عكس التلاميذ العاديين الذين يمكن كتابة فتحات لهم ، يسمح التلاميذ المقروءة فقط بالقراءة من تلك المواضع.
function foo(pair: readonly [string, string]) { console.log(pair[0]);
بنفس الطريقة التي يكون بها tuples العادية هي الأنواع التي تمتد من Array
- tuple مع عناصر من النوع T
1
و T
2
و ... T
n
يمتد من Array<
T
1
| T
2
| ... T
n
>
- tuples readonly
هي الأنواع التي تمتد من ReadonlyArray
. لذا فإن tuple readonly
مع العناصر T
1
و T
2
و ... T
n
تمتد من ReadonlyArray<
T
1
| T
2
| ... T
n
>
.
readonly
نوع معين readonly
ومصفوفات readonly
في الإصدارات السابقة من TypeScript ، قمنا بتعميم الأنواع المعينة للعمل بشكل مختلف على أنواع تشبه الصفيف. هذا يعني أن النوع المعين مثل Boxify
يمكن أن يعمل على المصفوفات Boxify
على حد سواء.
interface Box<T> { value: T } type Boxify<T> = { [K in keyof T]: Box<T[K]> }
لسوء الحظ ، كانت الأنواع المعينة مثل نوع الأداة المساعدة Readonly
غير فعالة على أنواع المصفوفات والأنواع.
في TypeScript 3.4 ، يقوم معدّل readonly
في نوع معين تلقائيًا بتحويل أنواع تشبه الصفيف إلى نظرائهم readonly
.
وبالمثل ، يمكنك كتابة نوع أداة مساعدة مثل النوع Writable
والذي يزيل readonly
، وهذا من شأنه تحويل حاويات الصفيف readonly
إلى معادلاتها القابلة للتغيير.
type Writable<T> = { -readonly [K in keyof T]: T[K] }
محاذير
على الرغم من مظهره ، لا يمكن استخدام معدّل الكتابة readonly
فقط إلا في بناء الجملة على أنواع الصفيف وأنواع الصفوف. انها ليست عامل نوع للأغراض العامة.
let err1: readonly Set<number>;
تأكيدات const
عند التصريح عن متغير أو خاصية قابلة للتغيير ، غالبًا ما يقوم TypeScript بتوسيع القيم للتأكد من أنه يمكننا تعيين الأشياء لاحقًا دون كتابة نوع صريح.
let x = "hello";
من الناحية الفنية ، كل قيمة حرفية لها نوع حرفي. أعلاه ، تم توسيع النوع "hello"
إلى string
الكتابة قبل استنتاج نوع لـ x
.
قد يكون أحد الآراء البديلة هو القول بأن x
لديه نوع الحرف الأصلي "hello"
وأنه لا يمكننا تعيين "world"
لاحقًا على هذا النحو:
let x: "hello" = "hello";
في هذه الحالة ، يبدو ذلك متطرفًا ، ولكنه قد يكون مفيدًا في مواقف أخرى. على سبيل المثال ، غالبًا ما يقوم TypeScripters بإنشاء كائنات مخصصة للاستخدام في النقابات التمييزية.
type Shape = | { kind: "circle", radius: number } | { kind: "square", sideLength: number } function getShapes(): readonly Shape[] { let result = [ { kind: "circle", radius: 100, }, { kind: "square", sideLength: 50, }, ];
يعد قابلية التشغيل أحد أفضل الأساليب البحثية التي يمكن لـ TypeScript استخدامها لتحديد وقت التوسع (بدلاً من تحليل برنامجنا بالكامل).
لسوء الحظ ، كما رأينا في المثال الأخير ، في خصائص JavaScript قابلة للتغيير افتراضيًا. هذا يعني أن اللغة ستعمل في الغالب على توسيع الأنواع غير المرغوب فيها ، مما يتطلب أنواعًا واضحة في أماكن معينة.
function getShapes(): readonly Shape[] {
لا بأس بهذا إلى حد ما ، لكن مع زيادة تعقيد هياكل البيانات الخاصة بنا ، يصبح هذا الأمر مرهقًا.
لحل هذا ، يقدم TypeScript 3.4 بنية جديدة للقيم الحرفية تسمى تأكيدات const
. بناء الجملة الخاص به هو تأكيد للنوع مع const
بدلاً من اسم النوع (على سبيل المثال 123 as const
). عندما نبني تعبيرات حرفية جديدة مع تأكيدات const
، يمكننا الإشارة إلى اللغة التي
- يجب عدم توسيع أنواع الحرف في هذا التعبير (على سبيل المثال عدم الانتقال من
"hello"
إلى string
) - حرفية الكائن الحصول على خصائص
readonly
- مجموعة الحرفي تصبح tuples
readonly
خارج ملفات .tsx
، يمكن أيضًا استخدام بناء جملة تأكيد قوس الزاوية.
غالبًا ما تعني هذه الميزة أنه يمكن حذف الأنواع التي يمكن استخدامها لولا ذلك لتوضيح قابلية التحويل إلى برنامج التحويل البرمجي.
لاحظ ما سبق لا يحتاج إلى تعليقات توضيحية من النوع. سمح تأكيد const
لـ TypeScript بأخذ أكثر أنواع التعبير تعبيرًا.
محاذير
شيء واحد هو أن نلاحظ أن التأكيدات const
لا يمكن إلا أن تطبق على الفور على التعبيرات الحرفية البسيطة.
شيء آخر يجب مراعاته هو أن سياقات const
لا تحول على الفور تعبيرًا ليكون غير قابل للتغيير تمامًا.
let arr = [1, 2, 3, 4]; let foo = { name: "foo", contents: arr, }; foo.name = "bar";
التحقق من النوع ل globalThis
قد يكون من الصعب بشكل مفاجئ الوصول إلى القيم أو الإعلان عنها في النطاق العالمي ، ربما لأننا نكتب الكود الخاص بنا في الوحدات النمطية (التي لا تتسرب إعلاناتها المحلية افتراضيًا) ، أو لأننا قد يكون لدينا متغير محلي يحجب اسم قيمة عالمية. في بيئات مختلفة ، هناك طرق مختلفة للوصول إلى ما هو فعال النطاق العالمي - global
في العقدة أو window
أو self
أو frames
في المتصفح ، أو this
في مواقع معينة خارج الوضع الصارم. لا شيء من هذا واضح ، وغالبًا ما يترك المستخدمين يشعرون بعدم التأكد من أنهم يكتبون الرمز الصحيح.
يقدم برنامج TypeScript 3.4 دعمًا للتحقق من النوع الجديد الخاص بـ ECMAScript الجديد - وهو متغير globalThis
يشير إلى النطاق العام. على عكس الحلول المذكورة أعلاه ، globalThis
يوفر globalThis
طريقة قياسية للوصول إلى النطاق العالمي الذي يمكن استخدامه عبر بيئات مختلفة.
globalThis
قادر أيضًا على إظهار ما إذا كان قد تم تعريف متغير globalThis
أم لا باعتباره const
خلال معاملته كخاصية readonly
عند الوصول إليه.
const answer = 42; globalThis.answer = 333333;
من المهم ملاحظة أن TypeScript لا يحول الإشارات إلى globalThis
عند التحويل البرمجي إلى الإصدارات القديمة من ECMAScript. على هذا النحو ، ما لم تكن تستهدف متصفحات دائمة الخضرة (التي تدعم بالفعل globalThis
) ، فقد ترغب في استخدام polyfill مناسب بدلاً من ذلك.
تحويل إلى المعلمات المسماة
في بعض الأحيان ، تبدأ قوائم المعلمات في الحصول على غير عملي.
function updateOptions( hue?: number, saturation?: number, brightness?: number, positionX?: number, positionY?: number positionZ?: number) {
في المثال أعلاه ، من السهل جدًا على المتصل أن يخلط ترتيب الوسيطات المقدمة. يتمثل أحد أنماط جافا سكريبت الشائعة في استخدام "كائن خيارات" بدلاً من ذلك ، بحيث يتم تسمية كل خيار بشكل واضح ولا يهم أي وقت مضى. يحاكي هذا ميزة أطلقت عليها لغات أخرى "المعلمات المسماة".
interface Options { hue?: number, saturation?: number, brightness?: number, positionX?: number, positionY?: number positionZ?: number } function updateOptions(options: Options = {}) {
لا يعمل فريق TypeScript فقط على برنامج التحويل البرمجي - بل نوفر أيضًا الوظائف التي يستخدمها المحررون للميزات الغنية ، مثل الإكمالات ، والانتقال إلى التعريف ، وإعادة البناء. في TypeScript 3.4 ، قام متدربنا Gabriela Britto بتنفيذ إعادة بيع جديدة لتحويل الوظائف الحالية إلى استخدام نمط "المعلمات المسماة".

على الرغم من أننا قد نغير اسم الميزة من خلال الإصدار 3.4 النهائي الخاص بنا ونعتقد أنه قد يكون هناك مجال لبعض بيئة العمل ، إلا أننا نود أن تجرب هذه الميزة وتعطينا ملاحظاتك.
كسر التغييرات
المستوى الأعلى يتم كتابة this
الآن
يتم الآن كتابة نوع المستوى الأعلى this
كـ typeof globalThis
بدلاً من any
. نتيجة لذلك ، قد تتلقى أخطاء للوصول إلى قيم غير معروفة في this
تحت noImplicitAny
.
لاحظ أن التعليمات البرمجية المترجمة تحت noImplicitThis
لن تواجه أي تغييرات هنا.
نشر وسيطات النوع العام
في بعض الحالات ، قد ينتج عن الاستنتاج المحسن الخاص بـ TypeScript 3.4 وظائف عامة ، بدلاً من تلك التي تأخذ وتعيد قيودها (عادةً {}
).
declare function compose<T, U, V>(f: (arg: T) => U, g: (arg: U) => V): (arg: T) => V; function list<T>(x: T) { return [x]; } function box<T>(value: T) { return { value }; } let f = compose(list, box); let x = f(100)
يمكن للتعليق التوضيحي الصريح على x
أن يتخلص من الخطأ.
ما التالي؟
يُعد TypeScript 3.4 أول إصدار لدينا يتضمن خطة تكرارية تحدد خططنا لهذا الإصدار ، والتي تهدف إلى التوافق مع خارطة الطريق التي مدتها 6 أشهر . يمكنك مراقبة كل من هؤلاء ، وعلى صفحة خريطة طريق ميزة المتداول لدينا عن أي عمل قادم.
في الوقت الحالي ، نتطلع إلى سماع تجربتك مع الصليب الأحمر ، لذلك قدمها الآن واطلعنا على أفكارك!