Typescript là gì? Ưu và nhược điểm của Typescript | Develop – Blog lập trình

Cụm từ “typescript” không còn quá xa lạ với một lập trình viên. Vậy có bao giờ bạn định nghĩa được “typescript” là gì chưa và nguyên tắc, ưu nhược điểm của nó. Hãy cùng Develop tìm hiểu sau bài viết sau đây nhé!

Typescript là gì? Ưu và nhược điểm của Typescript

Typescript là gì?

Để hiểu cặn kẽ về typescript thì trước tiên chúng ta phải định nghĩa được typescript là gì? đã

Typescript hiểu đơn giản chính là một ngôn ngữ được Microsoft cung cấp hoàn toàn miễn phí cho chúng ta. Nghe đến Typescript thì bạn đang mường tượng đến Javascript phải không? Nền tảng của TypeScript ít nhiều cũng có sự liên quan đến JavaScript vì nó chính là một ngôn ngữ mã nguồn mở của JavaScript. Type script đóng vai trò là dùng để thiết kế và xây dựng các dự án ứng dụng quy mô lớn mang tính chất phức tạp.

Typescript vs Javascript

Trái lại với sự đơn giản của JavaScript, dù cho TypeScript cũng đồng thời kế thừa nhiều định nghĩa, khái niệm của đa dạng các ngôn ngữ C#, Java,… nhưng TypeScript lại có yêu cầu cao về trật tự rõ ràng. 

Nhiều bạn hiểu theo “Typescript là phiên bản cao cấp của Javascript” thì cũng đúng, vì nó được kế thừa hầu như tất cả những gì của Javascript mà “bonus” thêm một số chức năng tiện lợi hơn, cải tiến hơn từ những yếu điểm của javascript như: các lớp hướng đối tượng và Static Structural typing, bên cạnh đó TypeScript còn có thể hoạt động rộng rãi cho các ứng dụng của ngôn ngữ Angular2 và Nodejs,…

Chức năng của TypeScript là gì?

Static Typing

Một trong những chức năng nổi bật của TypeScript chính là hỗ trợ cho việc static typing. Đồng nghĩa với việc bạn có thể khai báo kiểu cho biến, và trình biên dịch sẽ giảm được tỷ lệ gán sai kiểu của các giá trị.

Nếu khai báo kiểu bị bỏ qua, chúng sẽ được tự động phát hiện từ code của bạn.

Ví dụ: Các biến, tham số của hàm hoặc giá trị trả lại có thể có các kiểu được định nghĩa khi khởi tạo:

var blog: string = 'develop.com.vn',     // định nghĩa cho kiểu chuỗi (string) 
    post: number = 50,           // định nghĩa cho kiểu số (numberic)
    good: boolean = true;            // Kiểu True hoặc False

// Ngoài ra bạn cũng có thể khai báo dễ dàng hơn bằng kiểu:
// var blog = 'develop.com.vn';

// Hàm được mở rộng hơn với kiểu chuỗi hoặc là số.
// Nó sẽ không trả về bất cứ gì nên kiểu của hàm sẽ không được áp dụng ở đây.

function dev(blog: string, post: number): void {
  console.log("Blog của " + blog + " có hơn " + post + " bài viết.");
}

dev(blog, post);

Tất cả các khai báo kiểu sẽ bị xóa trong trường hợp TypeScript biên dịch thành JavaScript thành công

// JavaScript code from the above TS example.

var blog = 'develop.com.vn',
    post = 400, 
    good = true; 

function dev(blog, post) {
    console.log("Blog của " + blog + " có hơn " + post + " bài viết.");
}

dev(blog, post);
Trình biên dịch sẽ báo lỗi khi chúng ta thao tác không hợp lệ. Ví dụ:
// Gán kiểu boolean cho một biến, nhưng bạn lại gán giá trị cho chuỗi
var blog: boolean = "Lên develop.com.vn để xem blog";
Trình biên dịch sẽ bắt lỗi
main.ts(1,5): error TS2322: Type 'string' is not assignable to type 'boolean'.

Hệ thống cũng sẽ báo lỗi nếu thao tác truyền sai tham số tới một hàm:

function dev(blog: string, post: number): void{
  console.log("Blog của " + blog + " có hơn " + post + " bài viết.");
}

// Truyền Chuỗi vào hàm thay vì một biến
dev("Haha. Lên develop.com.vn đi", "Nhiều bài hay lắm á");

Hệ thống sẽ báo lỗi

main.ts(5,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

Một số kiểu dữ liệu phổ biến khi sử dụng typescript

  • Any – Nó có thể hiểu đơn giản là có thể truyền bất kỳ kiểu nào vô cũng được chấp thuận. Thường được dùng cho các biến khó xác định hoặc không xác định được kiểu, một số trường hợp là do dev “lười” gán kiểu ^.^
  • String – Là chuỗi thường được gán với dấu “” hoặc ”, một số trường hợp truyền thêm biến động thì sử dụng `${biến_động}`.
  • Number – Tất cả giá trị số trong hàm đều được biểu diễn bởi kiểu số, không có định nghĩa riêng cho số nguyên (interger), số thực (float) cũng như các kiểu khác.
  • Boolean – true hoặc false, không sử dụng 0 và 1 vì sẽ gây ra lỗi biên dịch.
  • Arrays – Có 2 kiểu cú pháp: my_arr: number[]; hoặc my_arr: Array<number>.
  • Void – sử dụng khi hàm không trả lại bất kỳ giá trị nào.

Interfaces

Interfaces có chức năng chính là sử dụng để kiểm tra xem một đối tượng có phù hợp với một cấu trúc nhất định hay không, trợ giúp trong giai đoạn giai đoạn phát triển.

Bằng cách định nghĩa một interface, ta có thể đặt tên trong trường hợp có sự kết hợp đặc biệt của các biến, đảm bảo rằng chúng luôn luôn đi cùng nhau.

Ví dụ:

// Định nghĩa 1 interface post
interface Post {
    name: string;
    view: number;
}

// Yêu cầu một bài viết có sườn chung. 
// Với interface chúng ta có thể biết được các thuộc tính cần luôn có sẵn
function dev(blog: Post): void{
  console.log("Bài viết " + blog.name + " có tổng cộng " + blog.view + " lượt xem.");
}

// Chúng ta cần xác định đối tượng bài viết có các thuộc tính đã khai báo
// Các kiểu của biến sẽ được tự động định nghĩa.
var develop = {
  name: "typescript", 
  view: 250
}

dev(develop);

Typescript ràng buộc răng thứ tự của các thuộc tính sẽ không quan trọng bằng việc chúng ta phải điền đủ số lượng các thuộc tính và đúng kiểu. Nếu một thuộc tính nào đó bị thiếu, hoặc sai kiểu, hoặc sai tên biến, trình biên dịch sẽ cảnh báo chúng ta.

interface Post {
    name: string;
    view: number;
}

function dev(blog: Post): void{
  console.log("Bài viết " + blog.name + " có tổng cộng " + blog.view + " lượt xem.");
}

// Ở đây, mình sẽ ví dụ về việc ghi sai tên biến
var develop = {
  nmae: "typescript", 
  view: 250
}

dev(develop);

Hệ thống sẽ cảnh báo
main.ts(16,7): error TS2345: Argument of type '{ nmae: string; calories: number; } 
is not assignable to parameter of type 'Food'. 
Property 'name' is missing in type '{ nmae: string; calories: number; }'.

Classes (lớp)

Trong các dự án, ứng dụng lớn, lập trình hướng đối tượng rất hay được các Dev sử dụng nhất là trong các ngôn ngữ như Java hoặc C#.

TypeScript cung cấp hệ thống class khá tương đồng với các ngôn ngữ này ví dụ như chức năng kế thừa, abstract classes, interface implementations, setter/getters, …

Từ phiên bản ECMAScript 2015 trở đi, classes được xem là một tính năng có sẵn trong JS và có thể không cần sử dụng TypeScript. Mặc dù 2 phiên bản này có nhiều chức năng tương tự nhau, nhưng chúng vẫn có điểm khác biệt, đó là TypeScript nghiêm ngặt hơn.

Ví dụ:

class Clothes {
  // Các thuộc tính chúng ta sẽ khai báo ở đây:
  // Mặc định sẽ public, nhưng bạn hoàn toàn có thể chuyển thành private hoặc protected.
  items: Array<string>;  // Phần tử của Clothes là mảng các chuỗi.
  size: number;         // Kích cỡ của phần tử Clothes.

  // Hàm đơn giản. 
  constructor(item_list: Array<string>, size_number: number) {
    // The this keyword is mandatory.
    this.items = item_list;    
    this.size = size_number;
  }

  // Phương thức
  list(): void {
    console.log("Danh sách quần áo hiện có:");
    for(var i=0; i<this.items.length; i++) {
      console.log(this.items[i]);
    }
  }

} 

// Tạo một biến sẽ gọi đến lớp Clothes.
var yourShirt = new Clothes(["Áo thun đỏ","Áo thun có cổ","Áo thun Polo"], 1);

// Gọi đến danh sách.
yourShirt.list();

Tính kế thừa. Nghe tên đã thấy thân thuộc cho dân C# và Java

class Shirt extends Clothes {
  // Thuốc tính

  // Khai báo hàm.
  constructor(item_list: Array<string>, size_number: number) {
    // Trong trường hợp này, chúng ta muốn cùng một hàm tạo như lớp cha (Clothes), 
    // Để tự động sao chép nó, chúng ta có thể gọi super () - một tham chiếu đến hàm tạo của hàm cha.
    super(item_list, size_number);
  }

  // Cũng giống như các thuộc tính, các phương thức được kế thừa từ phương thức gốc.
  // Tuy nhiên, chúng tôi muốn ghi đè hàm list () nên chúng tôi xác định lại nó.
  list(): void{
    console.log("Áo sơ mi:");
    for(var i=0; i<this.items.length; i++) {
      console.log(this.items[i]);
    }

  }
}

// Tạo một phiên bản mới của lớp Shirt
var shirt_man = new Shirt(["Áo đỏ","Áo có cổ","Áo bông"], 1);

// Lần này thông báo nhật ký sẽ bắt đầu với phần giới thiệu đặc biệt.
shirt_man.list();

Modules

Modules hóa rất quan trọng khi thực hiện các dự án lớn, phức tạp. Nó phân chia code thành nhiều thành phần nhỏ và lẻ ngoài ra còn có khả năng tái sử dụng giúp cho dự án của bạn dễ tổ chức và dễ hiểu hơn. Thay vì so với file có hàng ngàn dòng code.

TypeScript có chức năng exporting và importing các module, nhưng bản thân nó không thể xử lý thực sự việc liên kết giữa các file. Dùng require.js cho các ứng dụng client và CommonJS cho Node.js để cho phép modules TS dựa trên các thư viện của bên thứ ba.

Đặt trường hợp có 2 file: 1 file export một hàm, 1 file import, chúng ta sẽ gọi nó là:

exporter.ts

var sayHi = function(): void {
    console.log("Hello!");
}

export = sayHi;

importer.ts

import sayHi = require('./exporter');
sayHi();

Để có thể hoàn thành thao tác, cần download require.js và thêm nó trong một thẻ script – xem hướng dẫn typescript là gì của requirejs.org. Sau đó biên dịch 2 file .ts. Mộ tham số mở rộng cần được thêm vào để nói với TypeScript chúng ta đang xây dựng các module cho require.js (còn được gọi là AMD):

tsc --module amd *.ts

Generics

Generics là chức năng cho phép cùng một hàm có thể chấp nhận các tham số với nhiều kiểu khác nhau. Việc tạo ra các thành phần có thể tái sử dụng với generics tốt hơn sử dụng kiểu any, vì generics bảo tồn kiểu của các biến vào và ra của chúng.

Ví dụ: Generics trong ví dụ dưới đây đã nhận một tham số và trả lại một mảng chứa cùng tham số

// The <T> after the function name symbolizes that it's a generic function.
// When we call the function, every instance of T will be replaced with the actual provided type.

// Receives one argument of type T,
// Returns an array of type T.

function genericFunc<T>(argument: T): T[] {    
  var arrayOfT: T[] = [];    // Create empty array of type T.
  arrayOfT.push(argument);   // Push, now arrayOfT = [argument].
  return arrayOfT;
}

var arrayFromString = genericFunc<string>("beep");
console.log(arrayFromString[0]);         // "beep"
console.log(typeof arrayFromString[0])   // String

var arrayFromNumber = genericFunc(42);
console.log(arrayFromNumber[0]);         // 42
console.log(typeof arrayFromNumber[0])   // number

Lần đầu tiên gọi hàm chúng ta thiết lập kiểu thành string. Điều này không bắt buộc vì trình biên dịch có thể xem tham số được truyền và tự động quyết định kiểu nào phù hợp nhất, giống như lần gọi hàm thứ 2.

Mặc dù không bắt buộc, luôn luôn cung cấp kiểu được coi là cần thiết vì trình biên dịch có thể đoán sai kiểu trong các kịch bản phức tạp.

Tài liệu hướng dẫn của TypeScript là gì gồm một vài ví dụ cao cấp bao gồm generics classes, kết hợp chúng với interfaces, …ở typescriptlang.org.

Ưu điểm của Typescript là gì?

TypeScript thật sự thuận tiện và hoàn toàn miễn phí

Đối với loại ngôn ngữ lập trình tĩnh như TypeScript, tất cả những số liệu, thông số của bạn sẽ dễ dàng được lấy hơn nhờ IDE và trình biên dịch.

TypeScript hỗ trợ quá trình tìm kiếm giúp bạn tiết kiệm thời gian kiểm tra lại code, không cần thông qua bất cứ một ai để có thể tìm thông tin dữ liệu, ngoài ra TypeScript làm giảm phần trăm va chạm lỗi trong thời gian vận hành.

Ngoài ra, đây cũng là một trong những phần mềm nổi trội được Microsoft hỗ trợ hoàn toàn miễn phí.

Thao tác nhanh chóng và đơn giản hơn

Ngôn ngữ TypeScript có thao tác khá đơn giản, tiết kiệm thời gian hơn nhưng lại đem đến kết quả tốt đến bất ngờ, nó khắc phục tình trạng xuất hiện lỗi và dễ đọc hơn.

Cụ thể là, đối với ngôn ngữ thông thường người dùng thường thao tác theo các bước như:

  • Restart lại hàm, tạo đối số, hoàn thành đoạn mã
  • Sau khi apply hết các đoạn mã, công cụ cần thiết thì cho vận hành
  • Trong quá trình vận hành nếu phát hiện lỗi thì sửa chữa lại.

Tái cấu trúc

Chắc chắn trong quá trình viết code, các lập trình viên sẽ thường xuyên mắc phải nhiều lỗi nhỏ và cần chỉnh sửa, việc sử dụng TypeScript sẽ giúp bước chỉnh sửa code trở nên dễ dàng hơn nhờ hiệu quả của lệnh Rename Symbol/Find All Occurrences.

Đối với các ngôn ngữ khác, khi muốn sửa chi tiết nào đó thì thường phải thay đổi luôn những tập tin khác nếu có liên quan hoặc sử dụng RegEx

Trong trường hợp người dùng TypeScript muốn nâng cấp hệ thống của mình (thêm hoặc xóa thuộc tính, đổi tên,…) thì TypeScript sẽ giúp bạn tái cấu trúc lại sao cho phù hợp với nhu cầu tìm kiếm của bạn mà không gây náo loạn trong hệ thống. Trong trường hợp code của bạn không match được bất cứ dữ liệu nào thì sẽ được báo đến bạn ngay để được xử lý ổn thỏa.

Giảm tỷ lệ mắc lỗi trong hệ thống

Nhờ vào việc cảnh báo lỗi ngay khi viết code, nên tỷ lệ mắc lỗi trong hệ thống khi sử dụng TypeScript khá thấp, TypeScript sẽ trả lại giá trị null hoặc gợi ý thay đổi chỉnh sửa. Mỗi lần chỉnh sửa sau khi được TypeScript báo lỗi thì phần trăm hệ thống hoạt động mà không mắc phải lỗi là rất cao, có thể dễ dàng thấy được TypeScript giúp người dùng tiết kiệm không ít thời gian để sửa lỗi.

Hạn chế thử nghiệm Boilerplate

Với quy trình kiểm tra và báo lỗi tự động ngay khi code, khi bạn đã chắc chắn rằng các biến dữ liệu của mình nằm ở đúng chỗ thì bạn không cần phải lo hệ thống không vận hành hoặc không cần phải kiểm tra lại nữa.

Điều này sẽ giúp bạn tiết kiệm thời gian, không đặt quá nhiều chú ý vào những thao tác đơn giản cho việc kiểm tra mà có thể tận dụng thời gian tối ưu hơn bằng cách kiểm tra chất lượng logic của hệ thống.

Việc hạn chế được các bước thử nghiệm sẽ giúp tiết kiệm được thời gian hơn, nâng cao hiệu quả công việc của các lập trình viên.

Hợp nhất mã đơn giản

Sau khi hoàn thiện được một đoạn code và cho chúng chạy thử nghiệm, có thể ngay trong môi trường đó mọi thứ đều hoạt động trơn tru, nhưng bạn có chắc được đoạn code đó cũng sẽ hoạt động tốt khi ở trong môi trường điều kiện khác? 

Một trong những điểm mạnh của TypeScript là bạn có thể hợp nhất mã một cách đơn giản để có thể dễ dàng kiểm tra đánh giá đoạn mã bạn vừa mới cho ra đời kia bằng cách sử dụng Typedef – kiểm tra biên dịch.

Lại một lần nữa, TypeScript lại giúp người dùng tiết kiệm thời gian và công sức!

Hỗ trợ tối ưu hóa quy trình làm việc

TypeScript sẽ không khuyến khích người dùng nhảy bước, thực hiện sai thao tác. TypeScript khuyến khích người dùng đưa ra quyết định về kiểu dữ liệu khi sử dụng ngôn ngữ kiểu tĩnh trước khi thực hiện thao tác, các bước tiếp theo. Chính vì những quy luật như thế sẽ giúp cho các lập trình viên tối ưu được quy trình làm việc hiệu quả hơn.

Nhược điểm của Typescript là gì?

Bất kỳ ngôn ngữ nào cũng có điểm yếu và hạn chế của nó, và TypeScript cũng vậy, điểm hạn chế của TypeScript là:

Bắt buộc dùng biên dịch

Để có thể vận hành một tệp TypeScript với đuôi .js trên nền tảng Node.js bạn bắt buộc phải dùng trình biên dịch để có thể sử dụng.

Bước thiết lập cồng kềnh 

Trước khi có thể sử dụng được TypeScript, bạn cần đảm bảo rằng máy chủ Node.js, trình thử nghiệm và webpack đều có thể hoạt động với TypeScript, nếu không thì bạn sẽ không sử dụng được.

Bên cạnh đó, mỗi khi bạn apply thêm bất kỳ library nào như Redux, React và Styled-Component thì bạn cũng phải thêm Typedef vào.

Chỉ là phần ngôn ngữ mở rộng hỗ trợ

Sau cùng, chức năng của TypeScript cũng chỉ là để biên dịch về JavaScript, nó không phải là một ngôn ngữ có thể vận hành độc lập và nó cũng đồng thời không thể thay thế được vai trò của JavaScript. Chức năng của TypeScript bị giới hạn bởi chức năng của JavaScript, TypeScript chỉ là được nâng cấp từ điểm yếu của JavaScript.

Chỉ với mỗi TypeScript, người dùng không thể nào hoàn thiện được các công đoạn của dự án, công dụng của TypeScript chỉ thực sự nổi bật khi được kết hợp nhuần nhuyễn và tối ưu với các ngôn ngữ, nền tảng và tool khác.

TypeScript có thực sự là một mã nguồn mở?

Có nhiều luồng ý kiến cho rằng TypeScript là một mã nguồn mở, và đó cũng là một trong những lý do họ thích sử dụng TypeScript. Nhưng liệu đó có phải sự thật?

TypeScript thực sự là một mã nguồn mở nhưng nó vẫn nằm dưới sự chi phối của Microsoft – công ty phần mềm nổi tiếng về các phiên bản phần mềm độc quyền. 

Nhiều người dự đoán, TypeScript là một sản phẩm marketing của Microsoft dùng để thu hút người dùng về công năng và sự miễn phí. Tuy nhiên sau cùng, việc Microsoft có kéo dài việc miễn phí này hay không vẫn phụ thuộc rất nhiều vào Microsoft và người dùng hoàn toàn bị động trong chuyện này.

Cài đặt TypeScript

Cách dễ nhât để thiết lập TypeScript là thông qua trình quản lý NPM (Node.js).

Các bạn có thể dễ dàng thao tác và sử dụng thử các lệnh cơ bản, đơn giản sau đây dưới để có thể cài đặt TypeScript package toàn cục:

npm install -g typescriptjavascript:void(0)

Open bât kỳ cửa sổ terminal ở bất kỳ đâu và chạy lệnh tsc -v, nếu cài đặt thành công màn hình sẽ như thế này:

tsc -v
Version 1.8.10
Hướng dẫn biên dịch sang từ TypeScript sang JavaScript
TypeScript được viết trong các file .ts (hoặc .tsx cho JSX), nó không thể sử dụng trực tiếp trong trình duyệt và cần biên dịch thành JavaScript. Điều này có thể thực hiện với một số cách:
Sử dụng các task runner như Gulp
Trực tiếp trong Visual Studio hoặc các IDE và trình soạn thảo khác
Trong terminal sử dụng lệnh tsc
Đối với Newbie chúng nên bắt đầu từ cách dễ nhất:
Câu lệnh sau sẽ nhận một file TypeScipt là main.ts và chuyển nó thành JavaScipt main.js. Nếu main.js đã tồn tại nó sẽ bị ghi đè:
tsc main.ts
Trong cùng 1 thời điểm, chúng ta có thể biên dịch nhiều file bằng cách liệt kê chúng hoặc áp dụng các wildcard:
# Will result in separate .js files: main.js worker.js. tsc main.ts worker.ts     # Compiles all .ts files in the current folder. Does NOT work recursively. tsc *.ts
Chúng ta cũng có thể sử dụng tùy chọn –watch để tự động biên dịch một file TypeScript khi có thay đổi:
# Initializes a watcher process that will keep main.js up to date. tsc main.ts --watch
Một file tsconfig.json chứa nhiều thiết lập đôi khi cũng được viết bởi các TypeScript giàu kinh nghiệm. Các file như thế rất tiện lợi khi làm việc trên các dự án lớn có nhiều file .ts, nó hỗ trợ tự động hóa một phần tiến trình.