Tìm kiếm trang web

Tham số loại tổng quát T trong TypeScript là gì?


Đang đọc qua sổ tay TS. https://www.typescriptlang.org/docs/handbook/2/functions.html

Trong TypeScript, generic được sử dụng khi chúng ta muốn mô tả một sự tương ứng giữa hai giá trị. Chúng ta làm điều này bằng cách khai báo một tham số kiểu trong chữ ký hàm:

function firstElement<Type>(arr: Type[]): Type | undefined {
  return arr[0];
}

Bằng cách thêm một tham số kiểu Type vào hàm này và sử dụng nó ở hai vị trí, chúng ta đã tạo ra một liên kết giữa đầu vào của hàm (mảng) và đầu ra (giá trị trả về). Bây giờ khi chúng ta gọi nó, một kiểu cụ thể hơn sẽ xuất hiện:

Trong trường hợp này Type có phải là một từ khóa không? Khi tôi chỉ thấy T thì đó có phải là cùng một thứ không?

Tôi có đang hiểu phần này đúng không? Bằng cách thêm , chúng ta đang nói với Typescript để gán bất kỳ kiểu nào của đầu vào cho đầu ra?

Câu trả lời #1

Trong trường hợp này, Type có phải là một từ khóa không?

Trong ví dụ của bạn, Type là một tham số kiểu tổng quát (biến kiểu).

Khi tôi chỉ thấy T thì có phải là cùng một thứ không?

Giả sử token ở cùng vị trí, vâng.

Bằng cách thêm, chúng ta đang nói với Typescript để gán bất kỳ kiểu nào của đầu vào cho đầu ra?

Thật hữu ích cho tôi khi suy nghĩ về chúng tương tự như các tham số trong hàm, nhưng dành cho các kiểu. Về cơ bản, bạn đang nói với Typescript điều này:

"Tôi đang tạo một tham số kiểu (biến) có tên Type. Tôi sẽ nhận một đối số trong hàm này, đó sẽ là một mảng, và bạn nên sử dụng kiểu của từng phần tử trong mảng làm kiểu thực tế thay cho Type. Tôi sẽ trả về một trong các phần tử của mảng, vì vậy kiểu trả về của hàm này nên giống kiểu của một trong các phần tử của mảng (hoặc undefined nếu tôi sử dụng chỉ số mà tại đó không có giá trị)."

Bây giờ, có một phần có thể gây nhầm lẫn nữa về vấn đề này, dựa trên ví dụ mà bạn đã cung cấp, đó là "Tại sao TypeScript không tính đến khả năng undefined khi truy cập một phần tử mảng bằng cách sử dụng dấu ngoặc vuông?", và điều đó được giải thích trong câu trả lời này.

Đây là một ví dụ cụ thể:

Sân chơi TS

function firstElement<Type>(arr: Type[]): Type | undefined {
  return arr[0];
}

// This type is: number[]
const arr1 = [1, 2, 3];

// When giving `arr1` as the argument to `firstElement`,
// `Type` will become `number` because each element in `arr1`
// is `number`. So the result will be: number | undefined
const result1 = firstElement(arr1);

// This type is: string[]
const arr2 = ['hello', 'world'];

// When giving `arr2` as the argument to `firstElement`,
// `Type` will become `string` because each element in `arr2`
// is `string`. So the result will be: string | undefined
const result2 = firstElement(arr2);

Dưới đây là một ví dụ khác sử dụng T thay vì Type cho tham số kiểu tổng quát:

Sân chơi TS

function elementAtIndex<T>(arr: T[], index: number): T | undefined {
  return arr[index];
}

const arr = ['zero', 'one', 'two'];

const zero = elementAtIndex(arr, 0); // string | undefined
console.log(zero); // "zero"

const three = elementAtIndex(arr, 3); // string | undefined
console.log(three) // undefined

Chỉ để bạn biết, elementAtIndex trong ví dụ trên chỉ là phiên bản hàm của Array.prototype.at(), cái này sẽ có trong phiên bản TypeScript sắp tới (có thể là v4.6).

Câu trả lời #2

Không, ở đây Type là một định danh thông thường, dùng để xác định một tham số kiểu. Thông thường các tham số kiểu được đặt tên bằng các chữ cái in hoa, như T, nhưng các tên mô tả chi tiết hơn cũng rất hữu ích.

Tuyên bố này nói:

function firstElement   // We are defining a function
         <Type>         // The function has a type parameter
         (arr: Type[]): // and regular parameters of that type.
         Type | undefined // It returns either a value of the type
                          // given by the type parameter, or undefined.

Ý tưởng là bạn có thể truyền một mảng các phần tử của một loại cụ thể, và mong đợi một phần tử của cùng loại đó, được kiểm tra tĩnh:

firsElement<number>([1,2,3]) sẽ trả về một number, và trình biên dịch sẽ đảm bảo rằng nó sẽ không phải là một chuỗi hoặc một đối tượng.

firstElement<number>(['a', 'b']) thậm chí còn không thể biên dịch được, vì nó đang yêu cầu một mảng các số (theo <number>), nhưng lại nhận được một mảng các chuỗi.

firstElement<number>([]) sẽ trả về undefined, vì không có phần tử đầu tiên để trả về. Điều này được phép bởi mệnh đề | undefined trong kiểu trả về.