So sánh nhỏ: TypeScript vs JavaScript

So sánh nhỏ: TypeScript vs JavaScript

JavaScript và TypeScript chia sẻ nhiều điểm chung, tuy nhiên chúng cũng có những điểm riêng biệt tạo nên đặc trưng của từng ngôn ngữ. Bản thân mình và rất nhiều người xung quanh mình hiện nay đã chuyển dần từ JavaScript sang sử dụng TypeScript. Vậy nguyên nhân là gì? Điểm khác biệt của hai ngôn ngữ này là gì? Và quan trọng nhất: ngôn ngữ nào thì tốt hơn?

Trong bài viết này, mình sẽ so sánh sự khác biệt của hai ngôn ngữ này. Sự so sánh ở đây là dưới góc độ của một lập trình viên, chứ với người dùng bình thường thì không có lựa chọn nào khác ngoài JavaScript (mà người dùng bình thường thì quan tâm làm gì nhỉ 😀). Do kiến thức vô cùng rộng, mình cũng chỉ hiểu biết một phần nhỏ 😢, nên mình chỉ so sánh trong phạm vi đó được mà thôi 😅

JavaScript là gì?

JavaScript (JS) là ngôn ngữ lập trình phổ biến nhất thế giới hiện nay. Nó là một ngôn ngữ lập trình bậc cao cho phép tạo ra các ứng dụng web linh hoạt và có tương tác tốt cho người dùng. Cùng với với HTML, CSS, JavaScript là một trong những công nghệ "lõi" của ứng dụng web.

Đặc trưng của JavaScript là dynamic typing và trình thông dịch JIT (just in time). Ngoài ra, JavaScript hỗ trợ rất nhiều paradigm lập trình khác nhau, từ lập trình hàm, even-driven, OOP, v.v... JavaScript khởi đầu là ngôn ngữ client (tức là sẽ được thực thi trên trình duyệt), nhưng nó đã được phát triển để chạy được trên server (bằng NodeJS).

Dưới đây là một số tính năng nổi bật của JavaScript:

  • Ngôn ngữ lập trình phổ biến nhất thế giới
  • Chạy trên nhiều nền tảng, nhiều paradigm, dynamic typing
  • Chạy trên cả client và server
  • JIT
  • Tương thích tốt với mọi trình duyệt

Tuy nhiên, làm việc với JavaScript đang phát sinh nhiều vấn đề. Khi lượng code JavaScript ngày càng nhiều hơn, việc quản lý code sẽ khó hơn và Microsoft đã cố gắng tạo ra một ngôn ngữ khác để giải quyết những vấn đề này. Ngôn ngữ đó là TypeScript.

TypeScript là gì?

Như đã nói ở trên, JavaScript vốn không phải sinh ra để làm việc với lượng code lớn. Và làm việc với JavaScript sẽ gặp nhiều vấn đề khác nhau trong các dự án phức tạp. Do đó, TypeScript (TS) đã được tạo ra để giải quyết những vấn đề đó.

TypeScript được coi là superset của JavaScript, được tạo ra để giải quyết những bài toán của JavaScript với một cách làm tối ưu hơn. Nó vẫn tuân theo đặc tả kỹ thuật ECMAScript nên cú pháp của nó tương tự như JavaScript. Nhưng nó tốt hơn trong các dự án phức tạp do hỗ trợ strongly typed và cơ chế kiểm soát lỗi khi compile.

Trên thực tế, TypeScript hỗ trợ cả static typing và dynamic typing. Hơn thế nữa, nó còn cung cấp nhiều tính năng quan trọng của việc lập trình hướng đối tượng như: kế thừa, class, scope, namespace, interface và rất nhiều tính năng hiện đại khác.

TypeScript có thể dùng được cho cả client và server tương tự như JavaScript. Một ưu điểm nữa là các thư viện JavaScript cũng dùng được cho TypeScript.

Một số tính năng quan trọng của TypeScript:

  • Superset của JavaScript, tương thích với các thư viện có sẵn của JavaScript
  • Strongly typed, ngôn ngữ biên dịch (compile), tuân theo các nguyên tắc OOP
  • Dễ debug hơn
  • Hỗ trợ static typing

Một số lợi tích của TypeScript so với JavaScript:

  • TypeScript báo lỗi ngay khi compile, nhờ đó mà giảm được nhiều lỗi khi chạy trong khi JavaScript là ngôn ngữ thông dịch, dù code sai syntax thì lúc chạy mới báo lỗi.
  • TypeScript cho phép kiểm tra kiểu dữ liệu ngay khi compile, điều mà không bao giờ có ở JavaScript.
  • TypeScript có thể coi là JavaScript + các tính năng nâng cao. TypeScript compiler có thể dịch TypeScript sang tất cả các phiên bản JavaScript để chạy trên nhiều trình duyệt.

Vấn đề của JavaScript:

  • Về cơ bản, TypeScript là ngôn ngữ biên dịch, tức là nó cần thời gian để dịch thì mới chạy được. Và thông thường, TypeScript lại được dịch ra JavaScript để thực thi.

Trong phần tiếp theo, mình sẽ nói cụ thể hơn về sự khác biệt của hai ngôn ngữ này.

So sánh TypeScript và JavaScript

Định nghĩa

Trước hết, về mặt khái niệm, hai ngôn ngữ này đã có sự khác biệt lớn. JavaScript là ngôn ngữ script giúp tạo ra các trang web động trong khi TypeScript là superset của JavaScript với strongly typed.

Nói một cách đơn giản, TypeScript là JavaScript thêm một số tính năng nâng cao giúp việc lập trình đơn giản hơn, nhất là những tính năng liên quan đến kiểu dữ liệu và quản lý code phức tạp.

Tuy nhiên cũng cần lưu ý rằng, những tính năng hiện đại này được thêm vào ở mức cú pháp khi lập trình và quá trình biên dịch. Vì kết quả cuối cùng, TypeScript sẽ được dịch ra JavaScript để thực thi.

Cú pháp

Cả hai ngôn ngữ đều tuân theo đặc tả ECMAScript nên cú pháp có sự tương đồng rất lớn. Như mình và nhiều lập trình viên khác đã quen với JavaScript thì việc chuyển sang TypeScript cũng không hề khó khăn gì. Thậm chí vì cú pháp giống nhau, nếu lười thì cứ bên nguyên code JavaScript sang TypeScript là chạy được luôn.

Điểm khác biệt lớn nhất của TypeScript có lẽ là các biến cần được khai báo kiểu dữ liệu (hoặc tự nhận biết kiểu dữ liệu nếu có giá trị khởi tạo ban đầu). Tuy nhiên, cá nhân mình thấy TypeScript đã cố gắng tương thích ngược với JavaScript khi có một kiểu dữ liệu là any (khi không biết kiểu dữ liệu là gì thì dùng loại này, hoặc muốn code kiểu dynamic typing như JavaScript).

Trước đây, TypeScript được cho là tiên tiến hơn nhờ hỗ trợ lập trình hướng đối tượng. Tuy nhiên, kể từ ECMAScript 2015 thì JavaScript cũng bổ sung nhiều cú pháp OOP (tuy không đầy đủ như TypeScript). Thế nên, về cú pháp, có thể nói là hai ngôn ngữ này không có sự khác biệt lớn nào.

Biên dịch

Không có một yêu cầu nào về biên dịch JavaScript bởi nó được thiết kế để chạy trực tiếp trên trình duyệt (gần đây thì JavaScript có cần transpile để tương thích với các trình duyệt cũ). Một vấn đề của việc này là nhiều lỗi chỉ được phát hiện khi chạy.

Ví dụ bạn viết một hàm nhận tham số là string nhưng không gì có thể ngăn cản bạn và nhiều người khác truyền dữ liệu dạng int, float hay thậm chí undefined vào hàm đó. Mà một số tính toán (ví dụ +, -) có cách thức hoạt động rất khác với những kiểu dữ liệu khác nhau. Điều đó khiến việc debug và sửa lỗi của JavaScript mất thời gian hơn.

TypeScript thì khác, nó cần phải biên dịch và nó có thể phát hiện ra một số lỗi (như ở ví dụ trên) ngay ở bước này. Việc này có thể giúp lập trình viên tiết kiệm rất nhiều thời gian để tìm và sửa lỗi, thậm chí có thể giúp phòng tránh nhiều lỗi tiềm ẩn ngay từ khi lập trình. Điều này có ý nghĩa rất lớn khi làm việc trong một nhóm có nhiều người, khi người này thường hay sử dụng code của người khác.

Mặt trái của vấn đề là TypeScript cần phải biên dịch mới chạy được. Khiến việc lập trình và kiểm tra kết quả của TypeScript mất thời gian hơn, trong khi JavaScript có thể chạy trực tiếp luôn. Tuy nhiên, với những lợi ích như đã nói ở trên, thời gian chờ biên dịch và thực thi vẫn là quá nhỏ so với lợi ích mà nó mang lại.

Typing

JavaScript là dynamic typing, có nghĩa là một biến có thể nhận bất cứ kiểu dữ liệu nào (ví dụ integer sau đó lại gán thành string). Đây là một ưu điểm lớn với những script nhỏ (vài dòng đến vài chục dòng) vì nó giúp lập trình nhanh hơn. Nhưng với những ứng dụng lớn, có nhiều module, điều đó khiến việc xử lý dữ liệu nhiều khi rơi vào bế tắc do không biết dữ liệu của biến là gì (và nó đã bị thay đổi từ khi nào).

JavaScript không hỗ trợ static typing, là kiểu lập trình mà mỗi biến sẽ được khai báo kiểu dữ liệu trước và sẽ gặp lỗi nếu được gán giá trị có kiểu dữ liệu khác. TypeScript là ngôn ngữ cung cấp tính năng này.

Static typing là tính năng quan trọng nhất của TypeScript (có lẽ vì thế nó mới được đặt tên này). Nó cho phép lập trình viên biết được lỗi liên quan đến kiểu dữ liệu ngay khi compile.

Không chỉ ngôn ngữ, một số công cụ phát triển hiện đại (ví dụ vscode) cũng có nhiều tính năng để kiểm tra và phát hiện những lỗi kiểu này ngay khi code. Và rõ ràng là việc lint code TypeScript (nhờ static typing) dễ hơn hẳn JavaScript.

JavaScript có phải ngôn ngữ OOP hay không?

ECMAScript là đặc tả kỹ thuật của ngôn ngữ, nó đưa ra các cú pháp, hướng dẫn và nhiều mô tả khác về JavaScript (và cả TypeScript). Kể từ ECMAScript 2015 (ES6 hoặc ES2015), đặc tả kỹ thuật này đã thêm module, class, arrow function, object và nhiều tính năng thú vị khác liên quan đến OOP.

Kể từ ES6, lập trình viên JavaScript đã có thể dùng class. Tuy nhiên, tính năng này không thực sự là lập trình hướng đối tượng, vì nó hoạt động dựa trên cơ chế prototype của JavaScript. Vì là một ngôn ngữ dựa trên prototype (chứ không phải class, dù có thể code bằng từ khóa này), JavaScript không được coi là ngôn ngữ lập trình hướng đối tượng, mặc dù nó có thể tuân theo một vài nguyên tắc OOP.

TypeScript có phải ngôn ngữ OOP hay không?

Câu trả lời cho câu hỏi này thì lại hơi phức tạp một chút. TypeScript cũng có class như JavaScript và nhiều tính năng liên quan khác (namespace, interface, v.v...) cho phép lập trình viên lập trình hướng đối tượng.

Thế nhưng, TypeScript lại được dịch ra chính JavaScript để thực thi (vẫn phải dựa vào cơ chế prototype). Hơn nữa, khác với những ngôn ngữ lập trình hướng đối tượng tiêu chuẩn (ví dụ Java), TypeScript không bắt buộc phải lập trình theo kiểu OOP. Do đó, TypeScript cũng thường không được coi là một ngôn ngữ thuần hướng đối tượng.

Trên thực tế, TypeScript cũng tương tự như JavaScript, lập trình viên có thể lập trình theo nhiều paradigm khác nhau, như lập trình hàm hay lập trình thủ tục.

Ví dụ code của TypeScript và JavaScript

JavaScript

const mars = {
    name: "Mars",
    gravity: 3.721
};
mars.mass;
// undefined
function weight(mass, gravity) {
    return mass * gravity;
}

TypeScript: khai báo kiểu

// code này tương tự let destination: string nhưng không cần do
// TypeScript tự phát hiện kiểu dữ liệu
let destination = 'Mars';

Sử dụng enum trong TypeScript

TypeScript

enum Professions { Astronaut, RocketScientist, Mechanic }

Sau khi biên dịch thành JavaScript

var Professions;
(function (Professions) {
    Professions[Professions["Astronaut"] = 0] = "Astronaut";
    Professions[Professions["RocketScientist"] = 1] = "RocketScientist";
    Professions[Professions["Mechanic"] = 2] = "Mechanic";
})(Professions || (Professions = {}));

TypeScript: type alias

type Person =
    { type: Professions.Astronaut, name: string, isAtSpace: boolean} |
    { type: Professions.RocketScientist, name: string }

TypeScript: interfaces

interface Planet {
    name: string;
    gravity: number;
    // optional property (?)
    asteroids?: string[] | string;
}
const mars: Planet = {
    name: "Mars",
    gravity: 3.721
};
mars.mass;
// Error: Property 'mass' does not exist on type
// '{ name: string; gravity: number }'.

TypeScript: khai báo kiểu của tham số

function weight(mass: number, planet: Planet) {
    return mass * planet.gravity;
}
function printAsteroids(planet: Planet) {
    if (Array.isArray(planet.asteroids)) {
        console.log("Asteroids: " + planet.asteroids.join(", "));
    } else {
        console.log("Asteroids: " + planet.asteroids);
    }
}

TypeScript có tốt hơn JavaScript

JavaScript đã vươn lên thành ngôn ngữ lập trình phổ biến nhất thế giới nhiều năm liền, trong khi TypeScript mới chỉ phổ biến kể từ năm 2017. Theo khảo sát của StackOverflow thì JavaScript vẫn là ngôn ngữ phổ biến nhất thế giới nhưng TypeScript cũng đang vươn lên rất nhanh.

Sau khi so sánh, đối chiếu thì hầu hết lập trình viên đều công nhận rằng TypeScript mang nhiều tính năng hiện đại hơn JavaScript. Thế nhưng, nó có thực sự tốt hơn hay không?

Nói một cách công bằng, công cụ nào cũng vậy, nó sẽ tốt nhất nếu dùng cho bài toán thích hợp nhất. Với các dự án nhỏ, TypeScript không thực sự cần thiết. Trong những dự án như vậy, JavaScript lại cho thấy nó tốt hơn, nhờ khả năng tương thích tốt với trình duyệt và sự gọn nhẹ của nó (chạy luôn không cần compile hay config gì cả). Ví dụ như trang blog này của mình, nó chỉ là một trang tĩnh và hoàn toàn không cần nhiều code phải chạy, nên JavaScript là một lựa chọn chuẩn xác 👍.

So với JavaScript, việc tương thích với các trình duyệt là một điểm trừ lớn của TypeScript. Các trình biên dịch và transpile phải được cấu hình cẩn thận để có thể dịch TypeScript thành JavaScript đúng phiên bản có thể tương thích với các trình duyệt khác nhau. Và một khi có lỗi liên quan đến vấn đề này, việc tìm và sửa lỗi của TypeScript lại khó khăn hơn JavaScript.

Ngoài ra, với một ngôn ngữ script và dynamic typing như JavaScript, nó cho phép lập trình viên code nhanh hơn (chỉ cần đặt biến, không cần lo kiểu dữ liệu), rất thích hợp khi chỉ cần một lượng code nhỏ (các script dạng quick-and-dirty chẳng hạn). Static typing thích hợp cho các dự án lớn và phức tạp hơn.

Dynamic typing không thực sự là vấn đề gì quá lớn nếu lập trình viên có kỹ năng tốt và sự cẩn thận trong công việc. Rất nhiều ngôn ngữ dạng script (như Python là ngôn ngữ mình rất thích) cũng là dynamic typing mà không có vấn đề gì cả. Tuy nhiên, cá nhân mình cũng thấy nếu có static typing thì vẫn tốt hơn.

Một vấn đề nữa với TypeScript là nó tốn tài nguyên máy tính (CPU, RAM) để biên dịch code, trong khi JavaScript có thể nhìn thấy ngay sự thay đổi trên trình duyệt.

Thế nhưng, như đã nói ở trên, TypeScript là lựa chọn hợp lý hơn cho những dự án lớn và phức tạp. Và TypeScript vốn được tạo ra để làm việc đó. Việc refactor code TypeScript dễ dàng hơn. TypeScript dựa vào việc khai báo kiểu dữ liệu tường minh, cho phép làm việc nhóm tốt hơn, khi mà các lập trình viên đều hiểu rõ sự tương tác giữa các hàm và biến.

TypeScript có thể sẽ hơi mất thời gian vào thời điểm ban đầu (như cảm nhận của mình khi chuyển sang dùng TypeScript). Khi mà mọi thứ cần được khai báo kiểu dữ liệu nhưng các dữ liệu được sử dụng thường rất phức tạp và không có sẵn, lập trình viên cần định nghĩa luôn kiểu dữ liệu được sử dụng. Và mỗi khi có thay đổi liên quan đến kiểu dữ liệu, lập trình viên cũng phải cập nhật nhiều file hơn.

Điều đó khi có vẻ khá phức tạp, nhưng thực sự khi đã quen rồi thì mọi chuyện cũng khá nhẹ nhàng (vẫn mất công hơn JavaScript chút). Thế nhưng tác dụng của nó thì có thể nhìn thấy ngay. Nhờ khả năng phát hiện nhiều lỗi ngay từ bước compile, TypeScript giúp tăng hiệu quả công việc khi làm trong những tổ chức lớn, những hệ thống mà code biến động liên tục.

Mình đang dùng TypeScript để làm việc với React và thực sự nó đã tiết kiệm rất nhiều thời gian cho tất cả mọi người. Mỗi khi cần gọi hàm hay gọi component, mọi người đều biết cần phải truyền những dữ liệu gì. Và mỗi khi cần thay đổi, mỗi người cũng dễ dàng update tất cả những gì cần thiết, hầu như không có chuyện bỏ sót chỗ này chỗ kia (sót là báo lỗi ngay 👍).

TypeScript cũng tuân theo ECMAScript nên nó rất quen thuộc với các lập trình JavaScript. Nó cũng hoàn toàn tương thích với các thư viện JavaScript có sẵn, do đó với những dự án lớn, việc lựa chọn TypeScript là rất đáng.

(Với người mới bắt đầu) nên học TypeScript hay JavaScript?

Câu trả lời của mình là JavaScript. JavaScript là ngôn ngữ phổ biến hơn, có rất nhiều tài liệu, nhiều cộng đồng mà nhờ đó, việc học JavaScript sẽ dễ dàng hơn. Việc lập trình với JavaScript nhờ vào dynamic typing sẽ đơn giản hơn TypeScript.

Tuy nhiên, nhờ cả hai đều tuân theo cùng một đặc tả, nên cú pháp của hai ngôn ngữ rất giống nhau. Do đó, một khi đã học được JavaScript thì việc dùng TypeScript cũng không có khăn gì (có thể hơi bỡ ngỡ lúc ban đầu).

Kết luận

Hình ảnh dưới đây mô tả khá hay về sự khác biệt của JavaScript và TypeScript.

compare

JavaScript là một ngôn ngữ rất tuyệt, không phải tự nhiên mà nó trở thành ngôn ngữ phổ biến nhất. Tuy nhiên, không phải lúc nào nó cũng là lựa chọn đúng nhất (không riêng gì JavaScript mà ngôn ngữ nào chẳng thế 🤣). Với những dự án lớn và phức tạp, TypeScript là lựa chọn tốt hơn. Cũng giống như rất nhiều công cụ cùng tồn tại song song khác, cái nào tốt hơn cái nào luôn luôn phụ thuộc vào từng bài toán cụ thể.

#TypeScript #JavaScript #client-side script #comparison #dynamic typing #static typing

Tôi xin lỗi nếu bài viết có bất kỳ typo nào. Nếu bạn nhận thấy điều gì bất thường, xin hãy cho tôi biết.

Nếu có bất điều gì muốn nói, bạn có thể liên hệ với tôi qua các mạng xã hội, tạo discussion hoặc report issue trên Github.

Welcome




manhhomienbienthuy

Xin chào. Tôi là manhhomienbienthuy, nickname khác là naa. Đây là thế giới của tôi, chào mừng đến với thế giới của tôi…

Bài viết liên quan




Bài viết mới




Chuyên mục




Lưu trữ theo năm




Câu nói yêu thích




There's a big difference between knowing the name of something and knowing something.

– Richard P. Feynman –

Thông tin liên hệ




Cảm ơn bạn đã quan tâm blog của tôi. Nếu có bất điều gì muốn nói, bạn có thể liên hệ với tôi qua các mạng xã hội, tạo discussion hoặc report issue trên Github.