TypeScript cung cấp một cách để định nghĩa các trường (fields) trong lớp (class) là riêng tư. Điều này có nghĩa rằng các thuộc tính hoặc phương thức được đánh dấu là riêng tư sẽ không thể được truy cập từ bên ngoài lớp đó. Dưới đây là một số quy tắc liên quan đến trường riêng tư trong TypeScript:

1. Khai báo với Từ khóa private

Để định nghĩa một thuộc tính của lớp là riêng tư, bạn sử dụng từ khóa private. Các trường này chỉ có thể được truy cập và sửa đổi từ bên trong lớp hoặc các phương thức của nó.

class Person {
    private name: string;

    constructor(name: string) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

Trong ví dụ này, trường name là riêng tư và chỉ có thể truy cập qua phương thức getName().

2. Truy cập ngoài lớp không hợp lệ

Nếu cố gắng truy cập một trường private từ bên ngoài lớp, TypeScript sẽ báo lỗi biên dịch.

const person = new Person("John");
console.log(person.name); // Lỗi: 'name' is private and only accessible within class 'Person'

3. Khả năng kế thừa

Trong TypeScript, các trường private cũng không thể truy cập từ các lớp con kế thừa. Điều này bảo vệ hoàn toàn các thuộc tính hoặc phương thức khỏi sự can thiệp từ bất kỳ lớp nào ngoài lớp cha.

class Employee extends Person {
    constructor(name: string) {
        super(name);
    }

    printName() {
        console.log(this.name); // Lỗi: 'name' is private and only accessible within class 'Person'
    }
}

4. Trường # (ECMAScript Private Fields)

Ngoài từ khóa private, TypeScript hỗ trợ cú pháp trường riêng tư của ECMAScript với dấu #. Trường bắt đầu bằng dấu # cũng là riêng tư và chỉ có thể truy cập từ bên trong lớp.

class Car {
    #brand: string;

    constructor(brand: string) {
        this.#brand = brand;
    }

    getBrand() {
        return this.#brand;
    }
}

const myCar = new Car("Toyota");
console.log(myCar.#brand); // Lỗi: Private field '#brand' must be declared in an enclosing class

5. Khác biệt giữa private#

Mặc dù cả hai cách đều đảm bảo rằng các trường không thể truy cập từ bên ngoài, nhưng chúng có một số khác biệt:

  • Trường private của TypeScript chỉ hoạt động trong quá trình biên dịch. Sau khi biên dịch thành JavaScript, các trường này trở thành công khai trong mã nguồn.
  • Trường với dấu # tuân theo tiêu chuẩn ECMAScript và vẫn được bảo vệ sau khi biên dịch, ngay cả trong JavaScript.

6. Truy cập thông qua getter và setter

Bạn có thể tạo các phương thức getter và setter để kiểm soát việc truy cập vào các trường private. Điều này giúp duy trì tính đóng gói của lớp, đồng thời vẫn cung cấp một cách an toàn để đọc và ghi các giá trị.

class Rectangle {
    private width: number;

    constructor(width: number) {
        this.width = width;
    }

    getWidth(): number {
        return this.width;
    }

    setWidth(width: number): void {
        this.width = width;
    }
}

Trong ví dụ trên, trường width là riêng tư, nhưng có thể được truy cập và sửa đổi thông qua các phương thức getWidthsetWidth.

Kết luận, trong TypeScript, việc sử dụng các trường riêng tư với từ khóa private hoặc dấu # là cách để bảo vệ dữ liệu khỏi bị truy cập ngoài ý muốn. Các quy tắc này giúp bạn kiểm soát tốt hơn tính toàn vẹn của đối tượng và cải thiện tính đóng gói trong lập trình OOP.