Ce este nou în TypeScript 5.0: Declaratori, Const Type, Enums Improvement, Speed și multe altele!
Publicat: 2023-04-15TypeScript 5.0 a fost lansat oficial pe 16 martie 2023 și este acum disponibil pentru utilizare pentru toată lumea. Această versiune introduce multe funcții noi cu scopul de a face TypeScript mai mic, mai simplu și mai rapid.
Această nouă versiune modernizează decoratorii pentru personalizarea clasei, permițând personalizarea claselor și a membrilor acestora într-un mod reutilizabil. Dezvoltatorii pot adăuga acum un modificator const la o declarație de parametru de tip, permițând inferențe de tip const să fie implicite. Noua versiune face, de asemenea, toate enumerarile să unească enumări, simplificând structura codului și accelerând experiența TypeScript.
În acest articol, veți explora modificările introduse în TypeScript 5.0, oferind o privire în profunzime asupra noilor sale caracteristici și capabilități.
Noțiuni introductive cu TypeScript 5.0
TypeScript este un compilator oficial pe care îl puteți instala în proiect folosind npm. Dacă doriți să începeți să utilizați TypeScript 5.0 în proiectul dvs., puteți rula următoarea comandă în directorul proiectului:
npm install -D typescript
Acest lucru va instala compilatorul în directorul node_modules , pe care îl puteți rula acum cu comanda npx tsc
.
De asemenea, puteți găsi instrucțiuni despre utilizarea versiunii mai noi de TypeScript în Visual Studio Code în această documentație.
Ce este nou în TypeScript 5.0?
În acest articol, să explorăm 5 actualizări majore introduse în TypeScript. Aceste caracteristici includ:
Decoratori modernizati
Decoratorii sunt în TypeScript de ceva vreme sub un steag experimental, dar noua versiune îi aduce la curent cu propunerea ECMAScript, care este acum în etapa 3, ceea ce înseamnă că este într-o etapă în care este adăugată la TypeScript.
Decoratorii sunt o modalitate de a personaliza comportamentul claselor și al membrilor acestora într-un mod reutilizabil. De exemplu, dacă aveți o clasă care are două metode, greet
și 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();
În cazurile de utilizare din lumea reală, această clasă ar trebui să aibă metode mai complicate care să gestioneze o anumită logică asincronă și să aibă efecte secundare etc., în care ați dori să introduceți niște apeluri console.log
pentru a ajuta la depanarea metodelor.
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();
Acesta este un tipar care apare frecvent și ar fi convenabil să existe o soluție care să fie aplicată fiecărei metode.
Aici intervin decoratorii. Putem defini o funcție numită debugMethod
care apare după cum urmează:
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; }
În codul de mai sus, debugMethod
ia metoda originală ( originalMethod
) și returnează o funcție care face următoarele:
- Înregistrează un mesaj „Începe execuția metodei”.
- Transmite metoda originală și toate argumentele acesteia (inclusiv aceasta).
- Înregistrează un mesaj „Execuția metodei se termină”.
- Returnează orice metodă originală returnată.
Folosind decoratori, puteți aplica metoda debugMethod
metodelor dvs., așa cum se arată în codul de mai jos:
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();
Aceasta va scoate următoarele:
LOG: Entering method. Hello, my name is Ron. LOG: Exiting method. LOG: Entering method. I am 30 years old. LOG: Exiting method.
La definirea funcției de decorare ( debugMethod
), este transmis un al doilea parametru numit context
(este obiectul context — are câteva informații utile despre cum a fost declarată metoda decorată și, de asemenea, numele metodei). Puteți actualiza debugMethod
pentru a obține numele metodei din obiectul 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; }
Când rulați codul, rezultatul va purta acum numele fiecărei metode care este decorată cu decoratorul debugMethod
:
'greet' Execution Starts. Hello, my name is Ron. 'greet' Execution Ends. 'getAge' Execution Starts. I am 30 years old. 'getAge' Execution Ends.
Există mai multe în ceea ce puteți face cu decoratorii. Nu ezitați să verificați cererea de extragere originală pentru mai multe informații despre cum să utilizați decoratorii în TypeScript.
Prezentarea parametrilor de tip const
Aceasta este o altă versiune mare care vă oferă un nou instrument cu generice pentru a îmbunătăți inferența pe care o obțineți atunci când apelați funcții. În mod implicit, când declarați valori cu const
, TypeScript deduce tipul și nu valorile sale literale:
// Inferred type: string[] const names = ['John', 'Jake', 'Jack'];
Până acum, pentru a realiza inferența dorită, trebuia să utilizați afirmația const adăugând „as const”:
// Inferred type: readonly ["John", "Jake", "Jack"] const names = ['John', 'Jake', 'Jack'] as const;
Când apelați funcții, este similar. În codul de mai jos, tipul de țări dedus este 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'] });
Este posibil să doriți un tip mai specific al cărui mod de a remedia până acum a fost adăugarea afirmației as const
:
// Inferred type: readonly ["USA", "Canada", "India"] const names = getNamesExactly({ countries: ['USA', 'Canada', 'India'] } as const);
Acest lucru poate fi dificil de reținut și de implementat. Cu toate acestea, TypeScript 5.0 introduce o nouă caracteristică în care puteți adăuga un modificator const la o declarație de parametru de tip, care va aplica automat o inferență asemănătoare const ca implicită.
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'] });
Utilizarea parametrilor de tip const
permite dezvoltatorilor să exprime mai clar intenția în codul lor. Dacă o variabilă este intenționată să fie constantă și să nu se modifice niciodată, utilizarea unui parametru de tip const
asigură că nu poate fi niciodată modificată accidental.
Puteți verifica cererea de extragere originală pentru mai multe informații despre cum funcționează parametrul de tip const în TypeScript.
Îmbunătățiri la Enums
Enumerările din TypeScript sunt o construcție puternică care permite dezvoltatorilor să definească un set de constante denumite. În TypeScript 5.0, au fost aduse îmbunătățiri enumărilor pentru a le face și mai flexibile și mai utile.
De exemplu, dacă aveți următoarea enumerare transmisă într-o funcție:
enum Color { Red, Green, Blue, } function getColorName(colorLevel: Color) { return colorLevel; } console.log(getColorName(1));
Înainte de introducerea TypeScript 5.0, ați putea trece un număr de nivel greșit și nu ar genera nicio eroare. Dar odată cu introducerea TypeScript 5.0, va arunca imediat o eroare.
De asemenea, noua ediție transformă toate enumerarile în enumerari uniune prin crearea unui tip unic pentru fiecare membru calculat. Această îmbunătățire permite restrângerea tuturor enumerarilor și referirea membrilor lor ca tipuri:
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
Îmbunătățiri de performanță ale TypeScript 5.0
TypeScript 5.0 include numeroase modificări semnificative în structura codului, structurile de date și extensiile algoritmice. Acest lucru a ajutat la îmbunătățirea întregii experiențe TypeScript, de la instalare până la execuție, făcând-o mai rapidă și mai eficientă.
De exemplu, diferența dintre dimensiunea pachetului TypeScript 5.0 și 4.9 este destul de impresionantă.
TypeScript a fost recent migrat de la spații de nume la module, permițându-i să folosească instrumente moderne de construcție care pot realiza optimizări precum ridicarea scopului. De asemenea, eliminarea unui cod depreciat a redus aproximativ 26,4 MB din dimensiunea pachetului de 63,8 MB al TypeScript 4.9.
Iată câteva câștiguri mai interesante în viteză și dimensiune între TypeScript 5.0 și 4.9:
Scenariu | Timp sau dimensiune în raport cu TS 4.9 |
material-ui timpul de construire | 90% |
Ora de pornire a compilatorului TypeScript | 89% |
Timpul de construcție al dramaturgului | 88% |
Timpul de auto-construcție al compilatorului TypeScript | 87% |
Timpul de creare a Outlook Web | 82% |
Timpul de construire VS Code | 80% |
Typescript npm Dimensiunea pachetului | 59% |
Rezoluție Bundler pentru o rezoluție mai bună a modulului
Când scrieți o instrucțiune de import în TypeScript, compilatorul trebuie să știe la ce se referă importul. Face acest lucru folosind rezoluția modulului. De exemplu, atunci când scrieți import { a } from "moduleA"
, compilatorul trebuie să cunoască definiția a
în moduleA
pentru a verifica utilizarea acestuia.
În TypeScript 4.7, au fost adăugate două opțiuni noi pentru setările --module
și moduleResolution
: node16
și nodenext
.
Scopul acestor opțiuni a fost de a reprezenta mai precis regulile de căutare exacte pentru modulele ECMAScript din Node.js. Cu toate acestea, acest mod are câteva restricții care nu sunt aplicate de alte instrumente.
De exemplu, într-un modul ECMAScript din Node.js, orice import relativ trebuie să includă o extensie de fișier pentru ca acesta să funcționeze corect:
import * as utils from "./utils"; // Wrong import * as utils from "./utils.mjs"; // Correct
TypeScript a introdus o nouă strategie numită „bundler moduleResolution”. Această strategie poate fi implementată prin adăugarea următorului cod în secțiunea „compilerOptions” a fișierului de configurare TypeScript:
{ "compilerOptions": { "target": "esnext", "moduleResolution": "bundler" } }
Această nouă strategie este potrivită pentru cei care folosesc bundlere moderne, cum ar fi Vite, esbuild, swc, Webpack, Parcel și altele care utilizează o strategie de căutare hibridă.
Puteți verifica cererea de extragere originală și implementarea acesteia pentru mai multe informații despre cum funcționează bundler moduleResolution
în TypeScript.
Deprecieri
TypeScript 5.0 vine cu o oarecare amortizare, inclusiv cerințe de rulare, modificări lib.d.ts și modificări ale API-ului.
- Cerințe de rulare: TypeScript vizează acum ECMAScript 2018, iar pachetul stabilește o așteptare minimă pentru motor de 12.20. Prin urmare, utilizatorii Node.js ar trebui să aibă o versiune minimă de 12.20 sau o versiune ulterioară pentru a utiliza TypeScript 5.0.
- Modificări lib.d.ts: Au existat unele modificări la modul în care sunt generate tipurile pentru DOM, care pot afecta codul existent. În special, anumite proprietăți au fost convertite din tipuri literale numerice în numere, iar proprietățile și metodele pentru gestionarea evenimentelor de tăiere, copiere și lipire au fost mutate între interfețe.
- Modificări ale API-ului: unele interfețe inutile au fost eliminate și au fost aduse unele îmbunătățiri ale corectitudinii. TypeScript 5.0 s-a mutat și la module.
TypeScript 5.0 a depreciat anumite setări și valorile suppressImplicitAnyIndexErrors
importsNotUsedAsValues
, inclusiv target: ES3
, out
, noImplicitUseStrict
, keyofStringsOnly
, suppressExcessPropertyErrors
, noStrictGenericChecks
, preserveValueImports
charset
charsets.
Deși aceste configurații vor rămâne valabile până la TypeScript 5.5, va fi emis un avertisment pentru a alerta utilizatorii care le folosesc în continuare.
rezumat
În acest articol, ați învățat câteva dintre caracteristicile și îmbunătățirile majore pe care TypeScript 5.0 le aduce, cum ar fi îmbunătățiri ale enumărilor, rezoluției bundlerului și parametrilor de tip const, împreună cu îmbunătățiri ale vitezei și dimensiunii.
Dacă vă gândiți la TypeScript pentru următoarele proiecte, încercați gratuit Kinsta Application Hosting.
Acum e rândul tău! Ce caracteristici sau îmbunătățiri considerați cele mai atrăgătoare în TypeScript 5.0? Există unele semnificative pe care este posibil să le fi trecut cu vederea? Spune-ne în comentarii.