به طراح وب خوش آمدید.
TypeScript 5.0 به طور رسمی در ۱۶ مارس ۲۰۲۳ منتشر شد و اکنون برای همه در دسترس است. این نسخه بسیاری از ویژگیهای جدید را معرفی میکند که برای کوچکتر، سادهتر و سریعتر کردن TypeScript طراحی شدهاند.
این نسخه جدید دکوراتورهای سفارشی سازی کلاس را مدرن می کند و امکان استفاده مجدد از سفارشی سازی کلاس ها و اعضای آنها را فراهم می کند. توسعهدهندگان اکنون میتوانند اصلاحکننده const را به یک اعلان پارامتر نوع اضافه کنند و به خروجیهای ثابت مانند پیشفرض اجازه دهند. در نسخه جدید، تمام enum ها در enum ها ادغام می شوند که ساختار کد را ساده می کند و کار با TypeScript را سرعت می بخشد.
در این مقاله با بررسی دقیق ویژگی ها و قابلیت های جدید TypeScript 5.0 با تغییرات ایجاد شده در TypeScript آشنا می شوید.
شروع کار با TypeScript 5.0
TypeScript کامپایلر رسمی است که می توانید با استفاده از npm در پروژه خود نصب کنید. اگر می خواهید از TypeScript 5.0 در پروژه خود استفاده کنید، می توانید دستور زیر را در فهرست پروژه خود اجرا کنید:
npm install -D typescript
با این کار کامپایلر تنظیم می شود node_modules دایرکتوری که اکنون می توانید از آن راه اندازی کنید npx tsc
تیم
همچنین می توانید دستورالعمل های استفاده از نسخه جدیدتر TypeScript را در اینجا بیابید کد ویژوال استودیو در این مستندات.
چه چیزی در TypeScript 5.0 جدید است؟
در این مقاله، بیایید نگاهی به ۵ آپدیت اصلی معرفی شده برای TypeScript بیندازیم. این ویژگی ها عبارتند از:
دکوراتورهای ارتقا یافته
دکوراتورها برای مدتی تحت یک پرچم آزمایشی در TypeScript وجود داشتهاند، اما به لطف یک پیشنهاد ECMAScript که در حال حاضر در حال توسعه است، در نسخه جدید تسریع میشوند. مرحله ۳یعنی در مرحله اضافه شدن به 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'];
تا به حال، برای دستیابی به خروجی مورد نظر، باید از عبارت const استفاده می کرد و “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 ویژگی جدیدی را معرفی می کند که به شما امکان می دهد اصلاح کننده const را به یک اعلان پارامتر نوع اضافه کنید، که به طور پیش فرض خروجی ثابت مانند را به طور خودکار اعمال می کند.
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 در TypeScript یک ساختار قدرتمند است که به توسعه دهندگان اجازه می دهد مجموعه ای از ثابت های نامگذاری شده را تعریف کنند. در TypeScript 5.0، بهبودهایی در enum ها انجام شده است تا آنها را حتی انعطاف پذیرتر و مفیدتر کند.
به عنوان مثال، اگر enum زیر به تابع ارسال شود:
enum Color {
Red,
Green,
Blue,
}
function getColorName(colorLevel: Color) {
return colorLevel;
}
console.log(getColorName(1));
قبل از تایپ اسکریپت ۵٫۰، میتوانید شماره سطح اشتباهی را بدون خطا ارسال کنید. اما با معرفی TypeScript 5.0 بلافاصله خطا می دهد.
علاوه بر این، نسخه جدید تمام enum ها را به union enum تبدیل می کند و یک نوع منحصر به فرد برای هر عضو محاسبه شده ایجاد می کند. این بهبود به شما امکان میدهد همه فهرستها را محدود کنید و به عناصر آنها به عنوان انواع اشاره کنید:
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 و ۴٫۹ بسیار چشمگیر است.
TypeScript اخیراً از فضاهای نام به ماژول ها منتقل شده است و به آن اجازه می دهد از ابزارهای ساخت مدرن استفاده کند که می تواند بهینه سازی هایی مانند افزایش دامنه را انجام دهد. علاوه بر این، حذف برخی از کدهای قدیمی، حجم بسته TypeScript 4.9 را از ۶۳٫۸ مگابایت تقریباً ۲۶٫۴ مگابایت کاهش داد.
در اینجا چند برد جالب دیگر در سرعت و اندازه بین TypeScript 5.0 و ۴٫۹ آورده شده است:
سناریو | زمان یا اندازه نسبت به TS 4.9 |
زمان مونتاژ مواد رابط | ۹۰% |
زمان شروع کامپایلر TypeScript | ۸۹% |
زمان ساخت نمایشنامه نویس | ۸۸% |
زمان خود ساخت کامپایلر TypeScript | ۸۷% |
زمان ساخت وب Outlook | ۸۲% |
زمان ساخت کد VS | ۸۰% |
اندازه بسته typescript npm | ۵۹% |
وضوح بسته نرم افزاری برای وضوح بهتر ماژول
وقتی یک دستور import را در TypeScript می نویسید، کامپایلر باید بداند واردات به چه چیزی اشاره دارد. این کار را با استفاده از مجوز ماژول انجام می دهد. مثلا وقتی می نویسی import { a } from "moduleA"
کامپایلر باید تعریف را بداند a
V 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 wrapper” معرفی کرد. این استراتژی را می توان با افزودن کد زیر به بخش “compilerOptions” فایل پیکربندی TypeScript خود پیاده سازی کرد:
{
"compilerOptions": {
"target": "esnext",
"moduleResolution": "bundler"
}
}
این استراتژی جدید برای کسانی که از سازندگان مدرن مانند Vite، esbuild، swc، Webpack، Parcel و دیگران استفاده میکنند که از استراتژی جستجوی ترکیبی استفاده میکنند، مناسب است.
می توانی چک کنی درخواست اصلی کشش و اجرای آن برای اطلاعات بیشتر در مورد چگونگی moduleResolution
بستهکننده توسط TypeScript پشتیبانی میشود.
منسوخ شده
TypeScript 5.0 با تغییراتی همراه است، از جمله الزامات زمان اجرا، تغییرات lib.d.ts و تغییرات شکستن API.
- الزامات زمان اجرا: TypeScript اکنون ECMAScript 2018 را هدف قرار داده است و بسته حداقل مقدار مورد انتظار هسته را ۱۲٫۲۰ تنظیم می کند. بنابراین کاربران Node.js برای استفاده از TypeScript 5.0 باید حداقل نسخه ۱۲٫۲۰ یا بالاتر را داشته باشند.
- تغییرات در lib.d.ts: برخی تغییرات در نحوه تولید انواع برای DOM ایجاد شده است که ممکن است بر کد موجود تأثیر بگذارد. به طور خاص، برخی از ویژگیها از انواع عددی به انواع واقعی عددی تبدیل شدهاند و ویژگیها و روشهای مدیریت رویدادهای برش، کپی و چسباندن بین رابطها جابهجا شدهاند.
- شکستن تغییرات API: برخی از رابط های غیر ضروری حذف شده اند و برخی بهبودهای صحت انجام شده اند. TypeScript 5.0 نیز به ماژول ها منتقل شده است.
TypeScript 5.0 برخی از تنظیمات و مقادیر مربوط به آنها را منسوخ کرده است target: ES3
، out
، noImplicitUseStrict
، keyofStringsOnly
، suppressExcessPropertyErrors
، suppressImplicitAnyIndexErrors
، noStrictGenericChecks
، charset
، importsNotUsedAsValues
و preserveValueImports
و همچنین در ابتدا لینک هایی به پروژه اضافه کنید.
در حالی که این تنظیمات تا TypeScript 5.5 به قوت خود باقی خواهند ماند، هشداری برای هشدار به کاربرانی که هنوز از آنها استفاده می کنند صادر می شود.
خلاصه
در این مقاله، با برخی از ویژگیها و پیشرفتهای اصلی که TypeScript 5.0 به ارمغان میآورد، مانند بهبودهایی در enums، وضوح جمعآوری، و پارامترهای نوع const، و همچنین بهبود سرعت و اندازه، آشنا شدید.
اگر به TypeScript برای پروژه های بعدی خود فکر می کنید، Kinsta App Hosting را به صورت رایگان امتحان کنید.
نوبت شماست! چه ویژگیها یا پیشرفتهایی را در TypeScript 5.0 جذابتر میدانید؟ آیا موارد مهمی وجود دارد که ممکن است نادیده گرفته باشیم؟ در نظرات به ما اطلاع دهید.