TypeScript - Gli giao diện Generics

Xin chào bạn, ngôi sao lập trình tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới của TypeScript và khám phá một trong những tính năng mạnh mẽ nhất của nó: Gli giao diện Generics. Đừng lo lắng nếu bạn mới bắt đầu lập trình - tôi sẽ là người hướng dẫn thân thiện của bạn, và chúng ta sẽ cùng nhau bước từng bước. Cuối bài học này, bạn sẽ ngạc nhiên trước bao nhiêu điều bạn đã học được!

TypeScript - Generic Interfaces

Gli giao diện Generics là gì?

Trước khi chúng ta深入研究 gli giao diện generics, hãy nhanh chóng回顾 lại interfaces là gì trong TypeScript. Một interface giống như một hợp đồng định nghĩa cấu trúc của một đối tượng. Nó告诉 chúng ta đối tượng đó nên có những thuộc tính và phương thức nào.

Bây giờ, hãy tưởng tượng nếu chúng ta có thể làm cho những interfaces này linh hoạt hơn, có thể làm việc với nhiều loại dữ liệu khác nhau. Đó chính là nơi mà gli giao diện generics xuất phát! Chúng cho phép chúng ta tạo ra các interfaces có thể thích ứng với nhiều loại dữ liệu khác nhau, làm cho mã của chúng ta trở nên dễ tái sử dụng và linh hoạt hơn.

Gli giao diện Generics cơ bản

Hãy bắt đầu với một ví dụ đơn giản:

interface Box<T> {
contents: T;
}

let numberBox: Box<number> = { contents: 42 };
let stringBox: Box<string> = { contents: "Hello, TypeScript!" };

Trong ví dụ này, Box là một gli giao diện generics. <T> là như một placeholder cho một loại mà chúng ta sẽ xác định sau. Chúng ta có thể sử dụng interface này để tạo ra các boxes có thể giữ các loại item khác nhau:

  • numberBox là một Box giữ một số.
  • stringBox là một Box giữ một chuỗi.

Đó có phải là không tuyệt vời không? Nó giống như có một hộp kỳ diệu có thể thích ứng để giữ bất kỳ điều gì chúng ta bỏ vào!

Nhiều tham số loại

Gli giao diện generics có thể có hơn một tham số loại. Hãy nhìn vào một ví dụ:

interface Pair<T, U> {
first: T;
second: U;
}

let pair1: Pair<number, string> = { first: 1, second: "one" };
let pair2: Pair<boolean, Date> = { first: true, second: new Date() };

Ở đây, Pair là một gli giao diện generics với hai tham số loại, TU. Điều này cho phép chúng ta tạo ra các pairs của items mà mỗi item có thể là một loại khác nhau. Nó giống như tạo ra một cặp động của bất kỳ hai loại chúng ta muốn!

Gli giao diện với Phương thức

Interfaces cũng có thể bao gồm các phương thức, và các phương thức này có thể sử dụng các loại generics. Hãy xem một ví dụ:

interface Reversible<T> {
data: T[];
reverse(): T[];
}

class NumberArray implements Reversible<number> {
constructor(public data: number[]) {}

reverse(): number[] {
return this.data.slice().reverse();
}
}

let numbers = new NumberArray([1, 2, 3, 4, 5]);
console.log(numbers.reverse()); // Output: [5, 4, 3, 2, 1]

Trong ví dụ này, Reversible là một gli giao diện generics bao gồm một phương thức reverse(). Lớp NumberArray triển khai interface này cho số. Sự tuyệt vời của cách tiếp cận này là chúng ta có thể dễ dàng tạo ra các lớp tương tự cho chuỗi, đối tượng, hoặc bất kỳ loại nào khác!

Gli giao diện như Loại hàm

Bây giờ, hãy khám phá cách chúng ta có thể sử dụng gli giao diện generics để mô tả các loại hàm. Đây là nơi mà mọi thứ trở nên thực sự thú vị!

interface Transformer<T, U> {
(input: T): U;
}

let stringToNumber: Transformer<string, number> = (input) => parseInt(input);

console.log(stringToNumber("42")); // Output: 42

Trong ví dụ này, Transformer là một gli giao diện generics mô tả một hàm. Nó nhận vào một đầu vào của loại T và trả về một giá trị của loại U. Chúng ta sau đó tạo ra một hàm stringToNumber chuyển đổi một chuỗi thành một số sử dụng interface này.

Ví dụ thực tế: Xử lý dữ liệu

Hãy nhìn vào một ví dụ phức tạp hơn mà bạn có thể gặp phải trong lập trình thực tế:

interface DataProcessor<T, U> {
processItem(item: T): U;
processArray(items: T[]): U[];
}

class StringToNumberProcessor implements DataProcessor<string, number> {
processItem(item: string): number {
return parseInt(item);
}

processArray(items: string[]): number[] {
return items.map(item => this.processItem(item));
}
}

let processor = new StringToNumberProcessor();
console.log(processor.processItem("42"));          // Output: 42
console.log(processor.processArray(["1", "2", "3"])); // Output: [1, 2, 3]

Trong ví dụ này, chúng ta định nghĩa một DataProcessor interface có thể xử lý các item hoặc mảng các item. Lớp StringToNumberProcessor triển khai interface này để chuyển đổi các chuỗi thành số. Mẫu này rất hữu ích khi bạn cần xử lý dữ liệu theo nhiều cách khác nhau trong khi duy trì tính an toàn của loại.

Kết luận

Xin chúc mừng! Bạn vừa bước một bước lớn trong hành trình TypeScript của mình bằng cách học về gli giao diện generics. Những công cụ mạnh mẽ này cho phép chúng ta viết mã linh hoạt, dễ tái sử dụng và có thể làm việc với nhiều loại dữ liệu khác nhau. Hãy nhớ, thực hành là chìa khóa, vì vậy đừng ngại thử nghiệm với các khái niệm này trong các dự án của riêng bạn.

Dưới đây là bảng tham khảo nhanh các phương thức chúng ta đã bao gồm:

Phương thức Mô tả
interface Box<T> Tạo ra một gli giao diện generics cho một hộp có thể giữ bất kỳ loại nào
interface Pair<T, U> Tạo ra một gli giao diện generics cho một cặp item của loại khác nhau
interface Reversible<T> Tạo ra một gli giao diện generics với một phương thức để đảo ngược một mảng
interface Transformer<T, U> Tạo ra một gli giao diện generics cho một hàm chuyển đổi từ loại T sang loại U
interface DataProcessor<T, U> Tạo ra một gli giao diện generics để xử lý các item hoặc mảng các item

Tiếp tục lập trình, tiếp tục học hỏi, và hãy nhớ - trong thế giới của TypeScript, generics là siêu năng lực của bạn! ?‍♀️?‍♂️

Credits: Image by storyset