Để hiểu rõ hơn về TypeScript cũng như về khái niệm Type Erasure, một số định nghĩa quan trọng sau đây mà bạn cần nắm rõ.
Ngôn ngữ lập trình bậc cao và bậc thấp
Để hiểu rõ hơn về TypeScript, chúng ta cần phân biệt hai loại ngôn ngữ lập trình: ngôn ngữ bậc cao và ngôn ngữ bậc thấp.
Ngôn ngữ bậc cao, như JavaScript, dễ hiểu hơn đối với con người bởi tính trừu tượng hóa cao. Ngược lại, ngôn ngữ bậc thấp, điển hình là mã máy (nhị phân) hoặc Assembly, yêu cầu lập trình viên phải làm việc trực tiếp với địa chỉ bộ nhớ, khiến chúng trở nên phức tạp hơn.
Biên dịch (Compiling) và Chuyển đổi (Transpiling) là gì?
"Compiling" (biên dịch) và "transpiling" (chuyển đổi mã nguồn) là hai khái niệm khá tương đồng, nhưng không hoàn toàn giống nhau. "Compiling" là quá trình chuyển đổi mã nguồn thành mã máy (thường là mã nhị phân) để máy tính có thể thực thi. Quá trình này có thể diễn ra qua nhiều bước, mỗi bước sẽ tối ưu hóa mã và đưa nó đến gần hơn với mã máy. Java, C# và C là những ví dụ điển hình cho ngôn ngữ được biên dịch.
Trong khi đó, "transpiling" được hiểu là quá trình chuyển đổi từ một ngôn ngữ bậc cao này sang một ngôn ngữ bậc cao khác. Ví dụ, TypeScript là ngôn ngữ bậc cao, sau khi được "transpiled", nó sẽ trở thành JavaScript (cũng là ngôn ngữ bậc cao). Tương tự, Babel có thể chuyển đổi mã JavaScript ES6 thành ES5. Lợi ích của "transpiling" là bạn có thể viết mã bằng một ngôn ngữ bậc cao và vẫn có thể sử dụng được trong một ngôn ngữ bậc cao khác.
Type Erasure trong TypeScript
"Type Erasure" (xóa kiểu dữ liệu) là một phần quan trọng trong quá trình "transpiling" của TypeScript. Nói một cách đơn giản, "type erasure" là quá trình loại bỏ tất cả các kiểu dữ liệu khỏi mã TypeScript khi nó được chuyển đổi thành JavaScript. Các kiểu dữ liệu bạn sử dụng trong TypeScript sẽ không được kiểm tra trong thời gian chạy khi JavaScript được thực thi. Chúng chỉ được truy cập trong bước biên dịch/chuyển đổi mã nguồn.
Ví dụ, đoạn mã TypeScript: let name: string = 'Kealan'; sẽ được chuyển đổi thành let name = 'Kealan' trong JavaScript. Mặc dù kết quả có thể khác nhau tùy thuộc vào các bước xây dựng cụ thể, nhưng ví dụ về "type erasure" vẫn được thể hiện rõ ràng.
Điều này không chỉ áp dụng cho các kiểu dữ liệu nguyên thủy như number hay string mà còn với cả các kiểu dữ liệu tùy chỉnh do bạn tạo ra.
type StringType = string; const firstName: StringType = "Kealan";
Hiểu rõ về "type erasure" không chỉ giúp bạn nắm bắt khái niệm mà còn giải thích một bước quan trọng trong quá trình chuyển đổi mã nguồn, nơi các kiểu dữ liệu bị loại bỏ và không được sử dụng trong mã JavaScript được tạo ra. Điều này cũng có nghĩa là một số phần mã của bạn thậm chí không được "sử dụng" trong JavaScript trong bước "transpiling". Ví dụ, một interface gồm 100 dòng bạn tạo ra có thể bị loại bỏ hoàn toàn, giúp giảm kích thước mã được gửi đến người dùng.
Bạn có thể thấy rõ điều này trong TypeScript playground, nơi một interface được sử dụng trong mã TypeScript sẽ không xuất hiện trong mã JavaScript được chuyển đổi.
Hy vọng rằng bài viết này đã giúp bạn hiểu rõ hơn về TypeScript, cũng như sự khác biệt giữa "compiling" và "transpiling".