มีอะไรใหม่ใน TypeScript 5.0: Declarators, Const Type, Enums Improvement, Speed และอีกมากมาย!
เผยแพร่แล้ว: 2023-04-15TypeScript 5.0 เปิดตัวอย่างเป็นทางการเมื่อวันที่ 16 มีนาคม 2023 และตอนนี้ทุกคนสามารถใช้งานได้แล้ว รุ่นนี้แนะนำคุณสมบัติใหม่มากมายโดยมีจุดประสงค์เพื่อทำให้ TypeScript เล็กลง เรียบง่ายขึ้น และรวดเร็วขึ้น
รีลีสใหม่นี้ปรับปรุงตัวตกแต่งให้ทันสมัยสำหรับการปรับแต่งคลาส ทำให้สามารถปรับแต่งคลาสและสมาชิกในแบบที่นำกลับมาใช้ใหม่ได้ นักพัฒนาสามารถเพิ่มตัวแก้ไข const ให้กับการประกาศพารามิเตอร์ประเภทได้ ทำให้การอนุมานแบบ const เป็นค่าเริ่มต้น รีลีสใหม่ยังทำให้ enums union enums ทั้งหมด ทำให้โครงสร้างโค้ดง่ายขึ้น และเพิ่มความเร็วให้กับประสบการณ์ 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 คุณสมบัติเหล่านี้รวมถึง:
มัณฑนากรที่ทันสมัย
Decorator ใช้งาน 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();
ในกรณีการใช้งานจริง คลาสนี้ควรมีเมธอดที่ซับซ้อนกว่านี้ซึ่งจัดการกับลอจิก async บางอย่างและมีผลข้างเคียง ฯลฯ ซึ่งคุณต้องการโยนการเรียก 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 ในการประกาศพารามิเตอร์ประเภท ซึ่งจะใช้การอนุมานแบบ 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
Enums ใน TypeScript เป็นโครงสร้างที่มีประสิทธิภาพซึ่งช่วยให้นักพัฒนาสามารถกำหนดชุดของค่าคงที่ที่มีชื่อได้ ใน TypeScript 5.0 มีการปรับปรุง enums เพื่อให้มีความยืดหยุ่นและมีประโยชน์มากยิ่งขึ้น
ตัวอย่างเช่น หากคุณมี enum ต่อไปนี้ที่ส่งผ่านไปยังฟังก์ชัน:
enum Color { Red, Green, Blue, } function getColorName(colorLevel: Color) { return colorLevel; } console.log(getColorName(1));
ก่อนเปิดตัว TypeScript 5.0 คุณสามารถส่งหมายเลขระดับผิดได้ และจะไม่มีข้อผิดพลาดเกิดขึ้น แต่ด้วยการเปิดตัว TypeScript 5.0 จะทำให้เกิดข้อผิดพลาดทันที
นอกจากนี้ รีลีสใหม่ยังทำให้ enums ทั้งหมดเป็น union enums โดยการสร้างประเภทเฉพาะสำหรับแต่ละสมาชิกที่คำนวณ การปรับปรุงนี้ทำให้ enums ทั้งหมดแคบลงและการอ้างอิงสมาชิกเป็นประเภท:
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 ถูกย้ายจากเนมสเปซไปยังโมดูล ทำให้สามารถใช้ประโยชน์จากเครื่องมือสร้างสมัยใหม่ที่สามารถดำเนินการปรับให้เหมาะสม เช่น การยกขอบเขต นอกจากนี้ การลบโค้ดที่เลิกใช้แล้วบางส่วนได้ลดขนาดแพ็คเกจ 63.8 MB ของ TypeScript 4.9 ประมาณ 26.4 MB

ต่อไปนี้เป็นชัยชนะที่น่าสนใจอีกเล็กน้อยในด้านความเร็วและขนาดระหว่าง TypeScript 5.0 และ 4.9:
สถานการณ์ | เวลาหรือขนาดที่สัมพันธ์กับ TS 4.9 |
เวลาในการสร้างวัสดุ-UI | 90% |
เวลาเริ่มต้นของ TypeScript Compiler | 89% |
เวลาสร้างนักเขียนบทละคร | 88% |
TypeScript Compiler เวลาสร้างตัวเอง | 87% |
เวลาในการสร้างเว็บ Outlook | 82% |
VS เวลาในการสร้างโค้ด | 80% |
typescript npm ขนาดแพ็คเกจ | 59% |
ความละเอียดของ Bundler เพื่อความละเอียดของโมดูลที่ดีขึ้น
เมื่อคุณเขียนคำสั่งนำเข้าใน 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" } }
กลยุทธ์ใหม่นี้เหมาะสำหรับผู้ที่ใช้ Bundler สมัยใหม่ เช่น Vite, esbuild, swc, Webpack, Parcel และอื่นๆ ที่ใช้กลยุทธ์การค้นหาแบบผสมผสาน
คุณสามารถตรวจสอบคำขอดึงต้นฉบับและการใช้งานสำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของ moduleResolution
bundler ใน TypeScript
การเลิกใช้
TypeScript 5.0 มาพร้อมกับค่าเสื่อมราคา รวมถึงข้อกำหนดรันไทม์ การเปลี่ยนแปลง lib.d.ts และการเปลี่ยนแปลงการทำลาย API
- ข้อกำหนดรันไทม์: ขณะนี้ 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
และ preserveValueImports
รวมถึงส่วนนำหน้าในการอ้างอิงโครงการ
แม้ว่าการกำหนดค่าเหล่านี้จะยังคงใช้งานได้จนถึง TypeScript 5.5 คำเตือนจะออกเพื่อแจ้งเตือนผู้ใช้ที่ยังคงใช้งานอยู่
สรุป
ในบทความนี้ คุณได้เรียนรู้คุณลักษณะหลักและการปรับปรุงบางอย่างที่ TypeScript 5.0 นำมาใช้ เช่น การปรับปรุง enums ความละเอียดของ Bundler และพารามิเตอร์ประเภท Const พร้อมกับการปรับปรุงความเร็วและขนาด
หากคุณกำลังคิดเกี่ยวกับ TypeScript สำหรับโปรเจกต์ต่อไปของคุณ ลองใช้แอพพลิเคชั่นโฮสติ้งของ Kinsta ฟรี
ตอนนี้ถึงตาคุณแล้ว! คุณลักษณะหรือการปรับปรุงใดที่คุณพบว่าน่าสนใจที่สุดใน TypeScript 5.0 มีสาระสำคัญที่เราอาจมองข้ามไปหรือไม่? แจ้งให้เราทราบในความคิดเห็น.