Các Tính Năng Nâng Cao của TypeScript

Tạo bởi Hoàng Vũ, chỉnh sửa cuối lúc 18 tháng 3, 2025

TypeScript không chỉ cung cấp cú pháp JavaScript mạnh mẽ hơn mà còn bổ sung nhiều tính năng nâng cao giúp viết code linh hoạt và dễ bảo trì hơn.

Trong bài học này, chúng ta sẽ tìm hiểu:

  • Generics: Kiểu dữ liệu tổng quát giúp tái sử dụng code.
  • Decorators: Một tính năng quan trọng trong Angular.
  • Async/Await: Hỗ trợ lập trình bất đồng bộ dễ dàng hơn.
  • Type Guards: Kiểm tra kiểu dữ liệu trong runtime.
  • Namespaces & Modules: Quản lý code TypeScript tốt hơn.

Sau bài học này, bạn sẽ có thể sử dụng TypeScript một cách linh hoạt và áp dụng hiệu quả vào Angular.

Tìm hiểu các tính năng nâng cao của TypeScript trong Angular.

1. Generics: Kiểu dữ liệu tổng quát

Generics cho phép chúng ta tạo các hàm, lớp và interface linh hoạt hơn mà không cần chỉ định trước kiểu dữ liệu.

Ví dụ 1: Hàm sử dụng Generics

function identity<T>(value: T): T {
  return value;
}

console.log(identity<number>(42));    // Output: 42
console.log(identity<string>("Hello")); // Output: Hello

Giải thích:

  • T là một kiểu dữ liệu tổng quát (generic).
  • Khi gọi identity<number>(42), T sẽ là number.
  • Khi gọi identity<string>("Hello"), T sẽ là string.

Ví dụ 2: Lớp sử dụng Generics

class Box<T> {
  content: T;
  constructor(value: T) {
    this.content = value;
  }
}

let numberBox = new Box<number>(100);
console.log(numberBox.content); // Output: 100

Lợi ích của Generics

  • Giúp tái sử dụng code mà vẫn giữ được kiểu dữ liệu an toàn.
  • Hạn chế lỗi khi truyền sai kiểu dữ liệu.

2. Decorators: Tính năng quan trọng trong Angular

Decorators là một tính năng mạnh mẽ trong TypeScript giúp mở rộng và tùy chỉnh hành vi của lớp, phương thức hoặc thuộc tính. Decorators là nền tảng cho Angular (ví dụ @Component, @Injectable).

Ví dụ: Tạo một Decorator đơn giản

function Logger(constructor: Function) {
  console.log("Class is created:", constructor);
}

@Logger
class Person {
  name = "John";
}

Giải thích:

  • @Logger là một decorator áp dụng cho Person.
  • Khi Person được khởi tạo, decorator sẽ chạy trước và log ra console.

Ví dụ: Decorator cho phương thức

function Log(target: any, methodName: string, descriptor: PropertyDescriptor) {
  console.log(`Method: ${methodName} was called`);
}

class MathOperations {
  @Log
  multiply(a: number, b: number): number {
    return a * b;
  }
}

const math = new MathOperations();
math.multiply(2, 3); // Khi gọi hàm này, decorator sẽ log ra console

Lợi ích của Decorators

  • Giúp dễ dàng mở rộng chức năng của class mà không làm thay đổi code bên trong.
  • Là nền tảng của Angular (ví dụ: @Component, @Injectable).

3. Async/Await: Lập trình bất đồng bộ

Async/Await giúp xử lý tác vụ bất đồng bộ một cách dễ hiểu hơn thay vì dùng Promises hoặc Callbacks.

Ví dụ: Hàm bất đồng bộ với Async/Await

function fetchData(): Promise<string> {
  return new Promise((resolve) => {
    setTimeout(() => resolve("Dữ liệu đã tải xong!"), 2000);
  });
}

async function getData() {
  console.log("Đang tải dữ liệu...");
  let data = await fetchData();
  console.log(data);
}

getData();

Giải thích:

  • fetchData() trả về một Promise và mất 2 giây để hoàn thành.
  • await giúp chờ kết quả từ fetchData() mà không làm chương trình bị block.
  • Dữ liệu sẽ được tải xong sau 2 giây.

Lợi ích của Async/Await

  • Dễ đọc và hiểu hơn so với Promises.
  • Viết code bất đồng bộ giống như code đồng bộ.

4. Type Guards: Kiểm tra kiểu dữ liệu runtime

TypeScript hỗ trợ Type Guards để kiểm tra kiểu dữ liệu tại runtime.

Ví dụ: Kiểm tra kiểu dữ liệu bằng typeof

function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log("Chuỗi: " + value.toUpperCase());
  } else {
    console.log("Số: " + (value * 2));
  }
}

printValue("hello"); // Output: Chuỗi: HELLO
printValue(10); // Output: Số: 20

Ví dụ: Sử dụng Type Guards với class

class Dog {
  bark() {
    console.log("Woof!");
  }
}

class Cat {
  meow() {
    console.log("Meow!");
  }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark();
  } else {
    animal.meow();
  }
}

makeSound(new Dog()); // Output: Woof!
makeSound(new Cat()); // Output: Meow!

Lợi ích của Type Guards

  • Đảm bảo code chạy đúng kiểu dữ liệu.
  • Hạn chế lỗi khi làm việc với Union Types (|).

5. Namespaces & Modules: Quản lý code TypeScript tốt hơn

Namespaces

Namespace giúp gộp các class, function vào cùng một nhóm để tránh xung đột tên.

namespace Geometry {
  export class Circle {
    constructor(public radius: number) {}
    area() {
      return Math.PI * this.radius * this.radius;
    }
  }
}

let circle = new Geometry.Circle(10);
console.log(circle.area()); // Output: 314.16

Modules

Modules giúp tách nhỏ code thành nhiều file và tái sử dụng dễ dàng.

File user.ts

export class User {
  constructor(public name: string) {}
}

File main.ts

import { User } from "./user";

const user = new User("Alice");
console.log(user);

Lợi ích của Namespaces & Modules

  • Tránh xung đột tên biến giữa các file.
  • Tổ chức code tốt hơn khi dự án lớn.

Kết luận

  • Generics giúp code linh hoạt hơn mà vẫn đảm bảo an toàn kiểu dữ liệu.
  • Decorators là nền tảng của Angular, giúp mở rộng chức năng.
  • Async/Await giúp xử lý bất đồng bộ một cách dễ hiểu.
  • Type Guards giúp kiểm tra kiểu dữ liệu runtime.
  • Namespaces & Modules giúp tổ chức code TypeScript tốt hơn.
Website Logo

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.

Bình luận

Website Logo

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.

Liên hệ công việc qua email dưới đây.

lhvuctu@gmail.com

Chúng Tôi Trên

Bạn đang muốn học về lập trình website?

Bạn cần nâng cao kiến thức chuyên nghiệp hơn để nâng cao cơ hội nghề nghiệp? Liên hệ