Các kiểu dữ liệu trong TypeScript

Trong hướng dẫn này, bạn sẽ tìm hiểu về các kiểu dữ liệu trong TypeScript và mục đích của chúng.

Kiểu dữ liệu trong TypeScript là gì

Trong TypeScript, một kiểu dữ liệu là một cách thuận tiện để tham chiếu đến các thuộc tínhhàm khác nhau của một giá trị.

Giá trị là bất kỳ giá trị nào mà bạn có thể gán cho một biến, ví dụ: một số, một chuỗi, một mảng, một đối tượng và một hàm.

Xem giá trị sau:

'Hello'

Khi bạn nhìn vào giá trị này, bạn có thể nói rằng đó là một chuỗi. Và giá trị này có các thuộc tính và phương thức mà một chuỗi có.

Ví dụ: giá trị 'Hello' có một thuộc tính được gọi là length trả về số lượng ký tự trong chuỗi:

console.log('Hello'.length); // 5

Nó cũng có nhiều phương thức như match(), indexOf(), và toLocaleUpperCase(). Ví dụ:

console.log('Hello'.toLocaleUpperCase()); // HELLO

Nếu bạn nhìn vào giá trị 'Hello' và mô tả nó bằng cách liệt kê các thuộc tính và phương thức, sẽ rất bất tiện.

Một cách ngắn hơn để tham chiếu đến một giá trị là gán cho nó một kiểu dữ liệu. Trong ví dụ này, bạn nói rằng 'Hello' là một chuỗi. Sau đó, bạn biết rằng bạn có thể sử dụng các thuộc tính và phương thức của một chuỗi cho giá trị 'Hello'.

Tóm lại, trong TypeScript:

  • Một kiểu dữ liệu là một nhãn mô tả các thuộc tính và phương thức khác nhau mà một giá trị có.
  • Mỗi giá trị có một kiểu dữ liệu.

Các kiểu dữ liệu trong TypeScript

TypeScript kế thừa các kiểu dữ liệu được tích hợp sẵn trong JavaScript. Các kiểu dữ liệu trong TypeScript được phân loại thành:

  • Các kiểu dữ liệu nguyên thủy.
  • Cáckiểu dữ liệu đối tượng.

Các kiểu dữ liệu nguyên thủy

Bảng sau đây minh họa các kiểu dữ liệu nguyên thủy trong TypeScript:

Tên Miêu tả
string Đại diện cho dữ liệu văn bản
number Đại diện cho các giá trị số
boolean Có giá trị truefalse
null Có một giá trị: null
undefined Có một giá trị: undefined. Nó là một giá trị mặc định của một biến chưa được khởi tạo (gán giá trị)
symbol Đại diện cho một giá trị hằng số duy nhất
Các kiểu dữ liệu nguyên thủy trong TypeScript
Trong bài viết này bạn sẽ tìm hiểu cách khai báo và sử dụng các kiểu dữ liệu nguyên thủy trong TypeScript như number, string, boolean, ...

Các kiểu dữ liệu đối tượng

Các kiểu dữ liệu đối tượng là các hàm, mảng, lớp, v.v. Sau đó, bạn sẽ học cách tạo các loại đối tượng tùy chỉnh.

Các kiểu dữ liệu đối tượng trong TypeScript
Trong hướng dẫn này, bạn sẽ tìm hiểu về các kiểu dữ liệu đối tượng trong TypeScript và cách sử dụng chúng.

Mục đích của các kiểu dữ liệu trong TypeScript

Có hai mục đích chính của các kiểu dữ liệu trong TypeScript:

  • Các kiểu dữ liệu được trình biên dịch TypeScript sử dụng để phân tích mã của bạn để tìm lỗi.
  • Các kiểu dữ liệu cho phép bạn hiểu những giá trị nào được liên kết với các biến.

Ví dụ về các kiểu dữ liệu trong TypeScript

Ví dụ sau sử dụng phương thức querySelector() để chọn phần tử <h1>:

const heading = document.querySelector('h1');

Trình biên dịch TypeScript biết rằng kiểu dữ liệu của headingHTMLHeadingElement:

Và nó hiển thị danh sách các phương thức thuộc kiểu dữ liệu HTMLHeadingElementheading có thể truy cập:

Nếu bạn cố gắng truy cập thuộc tính hoặc phương thức không tồn tại, trình biên dịch TypeScript sẽ hiển thị lỗi. Ví dụ:

Type Annotation trong TypeScript

Type Annotation trong TypeScript là gì?

TypeScript sử dụng các chú thích kiểu dữ liệu (Type Annotation) để chỉ định rõ ràng kiểu dữ liệu cho biến, hàm, đối tượng, v.v.

TypeScript sử dụng cú pháp : type ngay sau mã định danh để làm chú thích kiểu dữ liệu, trong đó type có thể là bất kỳ kiểu dữ liệu hợp lệ nào.

Sau khi một mã định danh được chú thích bằng một kiểu dữ liệu, nó chỉ có thể được sử dụng với kiểu dữ liệu đó. Nếu mã định danh được sử dụng như một kiểu dữ liệu khác, trình biên dịch TypeScript sẽ báo lỗi.

Type Annotation cho biến và hằng số

Cú pháp sau cho thấy cách chỉ định chú thích kiểu dữ liệu cho biến và hằng số:

let variableName: type;
let variableName: type = value;
const constantName: type = value;

Trong cú pháp này, chú thích kiểu dữ liệu đứng ngay sau tên biến hoặc hằng số và bắt đầu bằng dấu hai chấm (:).

Ví dụ sau sử dụng chú thích kiểu dữ liệu number cho một biến:

let counter: number;

Sau đó, bạn chỉ có thể gán một giá trị kiểu số cho biến counter:

counter = 1;

Nếu bạn gán một giá trị kiểu chuỗi cho biến counter, bạn sẽ gặp lỗi:

let counter: number;
counter = 'Hello'; // compile error

Lỗi:

Type '"Hello"' is not assignable to type 'number'.

Bạn có thể vừa sử dụng chú thích kiểu dữ liệu cho một biến vừa khởi tạo giá trị cho nó trong cùng một câu lệnh như sau:

let counter: number = 1;

Trong ví dụ này, chúng tôi sử dụng chú thích kiểu số cho biến counter và gán giá trị 1 cho nó.

Sau đây là các ví dụ khác về chú thích kiểu dữ liệu nguyên thủy:

let name: string = 'John';
let age: number = 25;
let active: boolean = true;

Trong ví dụ này, biến name có kiểu dữ liệu là string, biến age có kiểu dữ liệu là number và biến active có kiểu dữ liệu là boolean.

Ví dụ về Type Annotation trong TypeScript

Type Annotation cho mảng

Để chú thích một kiểu mảng, bạn sử dụng một kiểu dữ liệu cụ thể và theo sau bởi một cặp dấu ngoặc vuông như sau : type[].

let arrayName: type[];

Ví dụ, phần sau khai báo một mảng kiểu chuỗi:

let names: string[] = ['John', 'Jane', 'Peter', 'David', 'Mary'];

Type Annotation cho đối tượng

Để chỉ định kiểu dữ liệu cho một đối tượng, bạn sử dụng chú thích kiểu dữ liệu đối tượng. Ví dụ:

let person: {
   name: string;
   age: number
};

person = {
   name: 'John',
   age: 25
}; // valid

Trong ví dụ này, đối tượng person chỉ chấp nhận một đối tượng có hai thuộc tính là: name có kiểu stringage có kiểu number.

Type Annotation cho đối số hàm và kiểu trả về

Phần sau trình bày chú thích hàm với chú thích kiểu dữ liệu tham số và chú thích kiểu dữ liệu trả về:

let greeting : (name: string) => string;

Trong ví dụ này, bạn có thể gán bất kỳ hàm nào chấp nhận một tham số đầu vào kiểu chuỗi và trả về kiểu chuỗi cho biến greeting:

greeting = function (name: string) {
    return `Hi ${name}`;
};

Ví dụ sau đây gây ra lỗi vì hàm được gán cho biến greeting không khớp với định nghĩa của nó.

greeting = function () {
    console.log('Hello');
};

Lỗi:

Type '() => void' is not assignable to type '(name: string) => string'. Type 'void' is not assignable to type 'string'.

Type Inference trong TypeScript

Suy luận kiểu dữ liệu (Type Inference) mô tả vị trí và cách TypeScript xác định kiểu dữ liệu khi bạn không chú thích kiểu dữ liệu một cách rõ ràng .

Suy luận kiểu dữ liệu cơ bản

Khi bạn khai báo một biến, bạn có thể sử dụng chú thích kiểu dữ liệu để chỉ định rõ ràng kiểu cho nó như đã được trình bày ở phần trên. Ví dụ:

let counter: number;

Tuy nhiên, nếu bạn khởi tạo giá trị cho biến counter thành một số, TypeScript sẽ suy ra kiểu dữ liệu của biến counternumber. Ví dụ:

let counter = 0;

Nó tương đương với câu lệnh sau:

let counter: number = 0;

Tương tự như vậy, khi bạn gán một giá trị cho tham số của hàm, TypeScript sẽ suy ra kiểu dữ liệu của tham số thành kiểu dữ liệu của giá trị mặc định. Ví dụ:

function setCounter(max = 100) {
    // ...
}

Trong ví dụ này, TypeScript suy ra kiểu dữ liệu của tham số max là kiểu number.

Tương tự, TypeScript suy ra kiểu dữ liệu trả về của hàm increment() là kiểu number:

function increment(counter: number) {
    return counter++;
}

Nó giống như:

function increment(counter: number) : number {
    return counter++;
}

Thuật toán kiểu dữ liệu chung tốt nhất

Hãy xem xét đoạn mã sau:

let items = [1, 2, 3, null];

Để suy ra kiểu dữ liệu của biến items, TypeScript cần xem xét kiểu của từng phần tử trong mảng.

Nó sử dụng thuật toán kiểu dữ liệu chung tốt nhất để phân tích kiểu dữ liệu của từng ứng viên và chọn kiểu dữ liệu tương thích với tất cả các ứng viên khác.

Trong trường hợp này, TypeScript chọn kiểu mảng số (number[]) là kiểu dữ liệu phổ biến nhất.

Nếu bạn thêm một chuỗi vào mảng items, TypeScript sẽ suy ra kiểu dữ liệu cho các phần tử là một mảng số và chuỗi:(number | string)[]

let items = [0, 1, null, 'Hi'];

Khi TypeScript không thể tìm thấy kiểu dữ liệu chung tốt nhất, nó sẽ trả về kiểu mảng liên hợp. Ví dụ:

let arr = [new Date(), new RegExp('\d+')];

Trong ví dụ này, TypeScript suy ra kiểu dữ liệu của arr sẽ là (RegExp | Date)[].

Kiểu dữ liệu theo ngữ cảnh

TypeScript sử dụng vị trí của các biến để suy ra kiểu dữ liệu của chúng. Cơ chế này được gọi là kiểu dữ liệu theo ngữ cảnh. Ví dụ:

document.addEventListener('click', function (event) {
    console.log(event.button); // 
});

Trong ví dụ này, TypeScript biết rằng tham số event là một thể hiện của MouseEvent vì sự kiện click.

Tuy nhiên, khi bạn thay đổi sự kiện click thành sự kiện scroll, TypeScript sẽ báo lỗi:

document.addEventListener('scroll', function (event) {
    console.log(event.button); // compiler error
});

Lỗi:

Property 'button' does not exist on type 'Event'.(2339)

TypeScript biết rằng event trong trường hợp này, là một thể hiện của UIEvent, không phải của MouseEvent. Và vì UIEvent không có thuộc tính button, do đó TypeScript sẽ báo lỗi.

Bạn sẽ tìm thấy kiểu dữ liệu theo ngữ cảnh trong các trường hợp có thể chẳng hạn như đối số cho lời gọi hàm, xác nhận kiểu, thành viên của đối tượng và mảng chuỗi, câu lệnh return và phía bên phải của phép gán.

Suy luận kiểu dữ liệu vs Chú thích kiểu dữ liệu

Bảng sau cho thấy sự khác biệt giữa suy luận kiểu và chú thích kiểu:

Suy luận kiểu dữ liệu Chú thích kiểu dữ liệu
TypeScript phải suy luận kiểu dữ liệu Bạn cho TypeScript biết rõ kiểu dữ liệu

Vì vậy, khi nào bạn sử dụng suy luận kiểu dữ liệu và chú thích kiểu dữ liệu?

Trong thực tế, bạn nên sử dụng suy luận kiểu dữ liệu càng nhiều càng tốt. Bạn chỉ nên sử dụng chú thích kiểu dữ liệu trong các trường hợp sau:

  • Khi bạn khai báo một biến và gán giá trị cho nó sau đó.
  • Khi bạn muốn chỉ định kiểu dữ liệu cho một biến không thể suy ra kiểu dữ liệu được.
  • Khi một hàm trả về kiểu dữ liệu any và bạn cần làm rõ giá trị.

Tóm lược

  • Mọi giá trị trong TypeScript đều có một kiểu dữ liệu.
  • Kiểu dữ liệu là một nhãn mô tả các thuộc tính và phương thức mà một giá trị có.
  • Trình biên dịch TypeScript sử dụng các kiểu dữ liệu để phân tích mã của bạn để tìm lỗi và lỗi.
  • Sử dụng chú thích kiểu dữ liệu với cú pháp : [type] để chỉ định rõ ràng kiểu dữ liệu cho một biến, hàm, giá trị trả về của hàm, v.v.
  • Suy luận kiểu dữ liệu xảy ra khi bạn khởi tạo biến, gán giá trị mặc định cho tham số và xác định kiểu dữ liệu trả về của hàm.
  • TypeScript sử dụng thuật toán kiểu dữ liệu chung tốt nhất để chọn kiểu dữ liệu của ứng viên tốt nhất tương thích với tất cả kiểu dữ liệu của các biến.
  • TypeScript cũng sử dụng kiểu dữ liệu theo ngữ cảnh để suy ra các kiểu dữ liệu của biến dựa trên vị trí của các biến.
TypeScript
Bài Viết Liên Quan:
Namespace trong TypeScript
Trung Nguyen 14/10/2021
Namespace trong TypeScript

Namespace được sử dụng để nhóm logic các chức năng. Namespace có thể bao gồm các interface, lớp, hàm và biến để hỗ trợ một nhóm các chức năng liên quan.

Từ khóa readonly và static trong TypeScript
Trung Nguyen 13/10/2021
Từ khóa readonly và static trong TypeScript

Trong hướng dẫn này bạn sẽ tìm hiểu về từ khóa readonly, static và cách sử dụng chúng trong TypeScript.

Từ khóa kiểm soát truy cập trong TypeScript
Trung Nguyen 12/10/2021
Từ khóa kiểm soát truy cập trong TypeScript

TypeScript có ba từ khóa kiểm soát quyền truy cập: public, private và protected để kiểm soát khả năng hiển thị của các thành phần dữ liệu của nó.

Abstract Class trong TypeScript
Trung Nguyen 11/10/2021
Abstract Class trong TypeScript

Định nghĩa một abstract class trong TypeScript bằng cách sử dụng từ khóa abstract. Abstract class chủ yếu được sử dụng để các lớp khác kế thừa từ chúng. Chúng ta không thể tạo một thể hiện của một abstract class.