Types và interface trong TypeScript
Trong bài trước , mình đã nói về sự khác biệt khi sử dụng "type" và "Interface" trong TypeScript một cách cụ thể và rõ ràng nhất rồi .
Trong bài viết này, mình sẽ tìm hiểu về Type Aliases, bao gồm Type và Interface, cũng như sự giống nhau và khác biệt giữa chúng. Ta cũng sẽ tìm hiểu về cách sử dụng Type Aliases trong TypeScript và khi nào nên sử dụng Type hoặc Interface để tạo kiểu dữ liệu tùy chỉnh.
Type Aliases (Type và Interface) trong TypeScript
TypeScript là một mở rộng của JavaScript, nó cung cấp kiểu dữ liệu tĩnh và nhiều tính năng mạnh mẽ để giúp kiểm tra và tối ưu hóa mã nguồn. Trong TypeScript, có hai cách chính để định nghĩa kiểu dữ liệu tùy chỉnh: Type và Interface. Cả hai đều có vai trò quan trọng trong việc tạo kiểu dữ liệu tùy chỉnh và quản lý mã nguồn.
Type Aliases (Type và Interface) là cách mà TypeScript cho phép bạn đặt tên cho kiểu dữ liệu phức tạp hơn, làm cho mã nguồn dễ đọc hơn và giúp tái sử dụng kiểu dữ liệu này trong nhiều nơi khác nhau trong mã. Mình sẽ tìm hiểu sâu hơn về cách sử dụng Type Aliases và hiểu rõ về sự giống nhau và khác biệt giữa Type và Interface.
Bài viết này được đăng tại [free tuts .net]
Sự giống nhau và khác biệt giữa Type và Interface
Sự giống nhau
Cả Type và Interface đều cho phép bạn định nghĩa kiểu dữ liệu tùy chỉnh trong TypeScript, và cả hai cách định nghĩa này có những điểm tương đồng:
-
Định nghĩa kiểu dữ liệu: Cả Type và Interface cho phép bạn định nghĩa kiểu dữ liệu tùy chỉnh. Bạn có thể sử dụng chúng để tạo kiểu dữ liệu phức tạp bằng cách kết hợp các kiểu dữ liệu cơ bản.
-
Tái sử dụng kiểu dữ liệu: Cả Type và Interface cho phép tái sử dụng kiểu dữ liệu trong nhiều phần của mã nguồn, giúp giảm sự lặp lại và tăng tính bảo trì.
Sự khác biệt
Mặc dù Type và Interface có nhiều điểm tương đồng, nhưng cũng có những khác biệt quan trọng:
Khi nào sử dụng Type:
- Sử dụng Type khi bạn cần định nghĩa kiểu dữ liệu mới hoặc tạo kiểu dữ liệu phức tạp bằng cách kết hợp các kiểu dữ liệu hiện có.
- Type có thể đại diện cho các kiểu dữ liệu cơ bản (số, chuỗi, boolean) hoặc kết hợp chúng để tạo kiểu dữ liệu phức tạp hơn.
- Type có thể sử dụng Union hoặc Intersection types để kết hợp các kiểu dữ liệu.
Khi nào sử dụng Interface:
- Sử dụng Interface khi bạn cần định nghĩa cấu trúc dữ liệu cho đối tượng, ví dụ như mô hình đối tượng hoặc hợp đồng giao tiếp giữa các phần của mã nguồn.
- Interface tạo ra một giao diện (shape) cho đối tượng và định nghĩa các thuộc tính và phương thức mà đối tượng phải tuân thủ.
Khi nào nên sử dụng Type
Một ví dụ cụ thể về khi nên sử dụng Type là khi bạn cần định nghĩa một kiểu dữ liệu Union để biểu diễn một biến có thể là kiểu A hoặc kiểu B.
type SoHoacChuoi = number | string;
Khi nào nên sử dụng Interface
Một ví dụ cụ thể về khi nên sử dụng Interface là khi bạn định nghĩa một giao diện cho đối tượng người dùng:
interface NguoiDung { ten: string; tuoi: number; dangNhap(): void; }
Trong ví dụ này, Interface giúp định nghĩa cấu trúc dữ liệu cho đối tượng NguoiDung và đảm bảo rằng mọi đối tượng NguoiDung sẽ có các thuộc tính và phương thức quy định.
Sử dụng Type Aliases trong TypeScript
Cú pháp cơ bản của Type
Type là một cách để định nghĩa kiểu dữ liệu tùy chỉnh trong TypeScript. Nó được sử dụng để đặt tên cho kiểu dữ liệu phức tạp hơn bằng cách kết hợp các kiểu dữ liệu cơ bản hoặc tạo ra các kiểu dữ liệu mới. Cú pháp đơn giản để định nghĩa Type như sau:
type TenKieu = KiểuDữLiệu;
Sử dụng Type Aliases để định nghĩa kiểu dữ liệu
Type Aliases cho phép bạn tạo kiểu dữ liệu phức tạp bằng cách kết hợp các kiểu dữ liệu có sẵn hoặc tạo ra kiểu dữ liệu mới. Ví dụ:
type ThongTinNguoiDung = { ten: string; tuoi: number; }; type DiemSo = number | string;
Trong ví dụ trên, mình đã định nghĩa Type Aliases ThongTinNguoiDung
để mô tả thông tin người dùng và DiemSo
để biểu diễn một kiểu dữ liệu có thể là số hoặc chuỗi.
Khả năng kết hợp và mở rộng kiểu dữ liệu với Type
Type cũng cho phép bạn kết hợp hoặc mở rộng kiểu dữ liệu. Bạn có thể sử dụng Type Aliases để tạo kiểu dữ liệu phức tạp hơn từ các kiểu dữ liệu đã có. Ví dụ:
type Nguoi = { ten: string; tuoi: number; }; type SinhVien = Nguoi & { mssv: string; };
Trong ví dụ này, mình đã tạo Type Aliases Nguoi
để đại diện cho thông tin cơ bản của một người, sau đó sử dụng SinhVien
để mở rộng Nguoi
bằng cách thêm một trường mã số sinh viên (mssv).
Sử dụng Interface trong TypeScript
Cú pháp cơ bản của Interface
Interface là một cách để định nghĩa cấu trúc dữ liệu cho đối tượng trong TypeScript. Nó được sử dụng để xác định các thuộc tính và phương thức mà một đối tượng phải tuân thủ. Cú pháp đơn giản để định nghĩa Interface như sau:
interface TenInterface { thuocTinh: KieuDuLieu; phuongThuc(): void; }
Sử dụng Interface để định nghĩa cấu trúc dữ liệu cho đối tượng
Interface cho phép bạn định nghĩa cấu trúc dữ liệu cho đối tượng và đảm bảo rằng đối tượng phải tuân thủ theo cấu trúc đó. Ví dụ:
interface Nguoi { ten: string; tuoi: number; } const nguoi1: Nguoi = { ten: "John", tuoi: 30, };
Trong ví dụ này,mình đã định nghĩa Interface Nguoi để mô tả cấu trúc dữ liệu của một người, sau đó sử dụng nó để kiểm tra đối tượng nguoi1.
Khả năng kết hợp và mở rộng Interface
Interface cũng cho phép bạn kết hợp hoặc mở rộng cấu trúc dữ liệu của nhiều đối tượng. Bạn có thể sử dụng Interface để tạo giao diện chung cho các đối tượng. Ví dụ:
interface Nguoi { ten: string; tuoi: number; } interface SinhVien extends Nguoi { mssv: string; } const sv1: SinhVien = { ten: "Alice", tuoi: 20, mssv: "12345", };
Trong ví dụ này, mình đã định nghĩa Interface Nguoi, sau đó tạo Interface SinhVien dựa trên Nguoi để mở rộng cấu trúc dữ liệu cho đối tượng SinhVien.
Sự so sánh giữa Type và Interface
Sự khác biệt về kết hợp và mở rộng kiểu dữ liệu
Type:
- Type cho phép bạn kết hợp (Union) hoặc tạo giao điểm (Intersection) giữa các kiểu dữ liệu.
- Ví dụ:
type SoHoacChuoi = number | string;
Interface:
- Interface không hỗ trợ Union hoặc Intersection types trực tiếp. Tuy nhiên, bạn có thể mở rộng một Interface từ một khác để kết hợp các cấu trúc dữ liệu.
- Ví dụ:
interface Nguoi { ten: string; tuoi: number; } interface SinhVien extends Nguoi { mssv: string; }
Sự khác biệt trong việc áp dụng kiểu dữ liệu cho các đối tượng
Type:
- Type có thể áp dụng cho các biến, hằng số, hoặc các tham số của hàm.
- Ví dụ:
const bien: SoHoacChuoi = 42;
Interface:
- Interface thường được sử dụng để định nghĩa cấu trúc của đối tượng (object shape). Bạn không thể áp dụng trực tiếp một Interface cho biến hay hằng số.
- Ví dụ:
const nguoi1: Nguoi = { ten: "John", tuoi: 30, }
Ví dụ minh họa về Type Aliases
Sử dụng Type Aliases để định nghĩa kiểu dữ liệu tùy chỉnh
Hãy xem xét một số ví dụ về cách sử dụng Type Aliases để định nghĩa kiểu dữ liệu tùy chỉnh và giải thích cụ thể cho mỗi ví dụ:
Ví dụ 1: Định nghĩa kiểu dữ liệu cho thông tin sản phẩm
type ThongTinSanPham = { ten: string; gia: number; moTa: string; }; const sanPham1: ThongTinSanPham = { ten: "Máy tính xách tay", gia: 1000, moTa: "Máy tính xách tay cao cấp." };
Trong ví dụ này, mình đã sử dụng Type Aliases ThongTinSanPham
để định nghĩa cấu trúc dữ liệu cho thông tin sản phẩm và sử dụng nó để kiểm tra đối tượng sanPham1
.
Ví dụ 2: Kết hợp kiểu dữ liệu
type Nguoi = { ten: string; tuoi: number; }; type SinhVien = Nguoi & { mssv: string; }; const sv1: SinhVien = { ten: "Alice", tuoi: 20, mssv: "12345", };
Trong ví dụ này, mình đã kết hợp hai kiểu dữ liệu Nguoi và SinhVien bằng cách sử dụng Type Aliases.
Sử dụng Type Aliases giúp cho việc định nghĩa và sử dụng kiểu dữ liệu tùy chỉnh trở nên rõ ràng và dễ quản lý trong mã nguồn TypeScript.
Kết bài
Trong bài viết này, mình đã tìm hiểu về Type Aliases (Type và Interface) trong TypeScript và sự khác biệt giữa chúng. Mình đã thấy cách sử dụng Type Aliases để định nghĩa kiểu dữ liệu tùy chỉnh, kết hợp và mở rộng kiểu dữ liệu, cũng như cách sử dụng Interface để định nghĩa cấu trúc dữ liệu cho đối tượng.
Ta đã thấy rằng lựa chọn giữa Type và Interface phụ thuộc vào yêu cầu cụ thể của dự án và cách bạn muốn tổ chức mã nguồn. Type Aliases cho phép bạn định nghĩa kiểu dữ liệu tùy chỉnh và kết hợp các kiểu dữ liệu, trong khi Interface giúp bạn định nghĩa cấu trúc dữ liệu cho đối tượng và đảm bảo tính đồng nhất trong mã nguồn.
Hãy lựa chọn một trong hai cách định nghĩa kiểu dữ liệu tùy thuộc vào bối cảnh và yêu cầu cụ thể của dự án của bạn. Sử dụng Type Aliases và Interface một cách thông minh để làm cho mã nguồn TypeScript của bạn dễ đọc, rõ ràng và dễ bảo trì.