Từ trước tới giờ, nếu ai đã từng viết Javascript thì sẽ biết rằng: Không giống như rất nhiều các ngôn ngữ lâp trình phổ biến hiện nay, Javascript không có khái niệm về Interface và khái niệm Class mới được đưa vào JS kể từ ES6.
TypeScript là ngôn ngữ do hãng Microsoft phát triển (Chính xác là do team của Anders Hejlsberg - tác giả ngôn ngữ C# - xây dựng nên). Vì vậy, thật dễ hiểu khi TypeScript - vốn được thiết kế như một superset của JavaScript - nay cũng được "cài cắm" thêm nhiều tính năng khác, trong đó có thể kể đến hai thứ mà ta sẽ nói tới trong bài viết này - Interface và Class. Tuy nhiên, vì xuất phát điểm ban đầu của JavaScript không phải là 1 ngôn ngữ hướng đối tượng hoàn toàn như C#, Java ... Vì thế, khái niệm về Interface cũng như Class được implement vào trong TypeScript chắc chắn cũng sẽ có những điểm khác biệt so với khái niệm mà ta đã quen thuộc ở các ngôn ngữ kia.
1. Class
JavaScript thông thường sử dụng function và nguyên lý kế thừa dựa trên prototype để viết nên các component có khả năng sử dụng lại. Còn đối với các dev đã quen với các ngôn ngữ OOP như C#, java ... việc kế thừa được xây dựng dựa theo kế thừa của các class.
Typescript (và sau này là ES6) đưa vào khái niệm Class cho JavaScript:
class Human { name: string; constructor(name: string) { this.name = name; } say() { console.log "hello, my name is: " + this.name; } } let John = new Human('John');
Cú pháp trên giống hoàn toàn như khi ta viết với C# hay java. Ta khai báo một class mới
Human. Class này bao gồm 3 member: 1 property name, hàm khởi tạo và method say. Cuối cùng, ta khởi tạo đối tượng thuộc lớp này bằng từ khóa new.Khi được dịch ra JavaScript để chạy, đoạn code trên sẽ trở thành như sau:
var Human = (function() { function Human(name) { this.name = name; } Human.prototype.say = function() { console.log("hello, my name is: " + this.name); }; return Human; })();
Từ đoạn code trên, ta có thể thấy rằng bản chất của class trong TypeScript cũng chính là việc sử dụng self-invoke function cùng với prototype của JavaScript .
2. Inheritance class
Đã có class thì phải có inheritance class. Nguyên lý kế thừa trong TypeScript cũng giống các ngôn ngữ khác:
class Teacher extends Human { say() { super.say(); console.log(" and I'm a teacher"); } }
Ta khai báo kế thừa lớp bằng từ khóa
extends. Trong class con, ta có thể gọi tới function của class cha bằng thông qua super.3. Khác #1: public, private, protected modifier
Với ví dụ ở trên, ta hoàn toàn có thể gọi tới property của class
Human như sau:let John = new Human('John'); let name = John.name;
Khác với C#: Đối với class trong TypeScript, nếu không có khai báo gì thêm, 1 property được mặc định coi như là public.
Bên cạnh đó, ta cũng có các modifier
private, protected cho property, đồng thời cũng có thể dùng modifier public để tăng readable cho code.class Human { public name: string; // public ở đây là optional }
Với private, property không thể bị gọi từ ngoài vào.
class Human { private name: string; } let John = new Human('John'); let name = John.name; // Error: 'name' is private;
Với protected, nó giống với private với 1 ngoại lệ là các property này có thể được gọi tới từ bên trong lớp con kế thừa từ lớp cha.
class Human { protected name: string; } class Teacher extends Human { say() { this.name; // Error nếu name được khai báo private ở trên. } }
4. Trick #1: parameter property
Việc khai báo 1 property, đồng thời gán giá trị cho nó ở constructor là việc thường thấy:
class Human { name: string; constructor(name: string) { this.name = name; } }
Pattern code này được sử dụng thường xuyên, nhiều đến nỗi Typescript đã cung cấp 1 cách gõ tắt: Cho phép tạo và khởi tạo property ở cùng 1 chỗ. Đoạn code có thể viết lại ngắn hơn như sau:
class Human { constructor(public name: string) { this.name = name; } }
Tương tự như thế, sử dụng các
modifier khác ở constructor cũng sẽ tạo cho ta các property tương ứng: private, protected, readonly.