hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Cấu trúc dữ liệu và giải thuật
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
      • NodeJS
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
      • MongoDB
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
    • Lập trình C#
      • Lập Trình C# Cơ Bản
      • ASP.NET Core MVC
    • Machine Learning
    • Git và Github
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • Typescript cơ bản
TypeScript cơ bản – Generics và keyof: tái sử dụng mà vẫn giữ kiểu

TypeScript cơ bản – Generics và keyof: tái sử dụng mà vẫn giữ kiểu

  • 17-10-2026
  • Toanngo92
  • 0 Comments

Giả sử bạn cần lấy phần tử đầu tiên của mảng tên khóa học, rồi lại cần làm điều tương tự với mảng số. Viết hai hàm giống nhau gây lặp; dùng any làm mất thông tin kiểu. Generics mô tả mối liên hệ giữa đầu vào và đầu ra để một định nghĩa có thể làm việc với nhiều kiểu cụ thể.

Mục lục

  • 1. Từ hàm cụ thể đến hàm generic
  • 2. Tái sử dụng cấu trúc dữ liệu
  • 3. Ràng buộc bằng extends
  • 4. keyof và truy cập thuộc tính có kiểm soát
  • 5. Khi nào nên dùng generics?
  • Đọc tiếp trong loạt bài

1. Từ hàm cụ thể đến hàm generic

function first<T>(items: readonly T[]): T | undefined {
  return items[0];
}
const firstTitle = first(["HTML", "TypeScript"]);
const firstId = first([10, 20]);
console.log(firstTitle?.toUpperCase()); // HTML
console.log(firstId); // 10

T là tham số kiểu, không phải một biến nhận giá trị lúc chạy. Trong lần gọi đầu, TypeScript suy luận T là string; lần tiếp theo T là number. Kiểu trả về có undefined vì mảng có thể rỗng. Với noUncheckedIndexedAccess, trình biên dịch cũng giúp nhắc trường hợp này.

Readonly ở tham số cho biết hàm chỉ đọc mảng thông qua tham chiếu này. Không nhất thiết phải truyền kiểu tường minh; khi cần mô tả một mảng rỗng có chủ ý, bạn có thể viết first<string>([]). Kết quả lúc chạy vẫn là undefined, vì khai báo kiểu không tạo phần tử cho mảng.

2. Tái sử dụng cấu trúc dữ liệu

interface Page<T> {
  items: T[];
  total: number;
}
interface Course {
  id: number;
  title: string;
}
const page: Page<Course> = {
  items: [{ id: 1, title: "TypeScript" }],
  total: 1
};

Page mô tả cấu trúc phân trang chung, còn T quyết định kiểu của từng phần tử. Page<Course> và Page<string> chia sẻ cách tổ chức nhưng giữ thông tin khác nhau ở items. Định nghĩa này chỉ kiểm tra cách dùng trong mã; nó không tự xác nhận kết quả trả về từ một API.

3. Ràng buộc bằng extends

function printTitle<T extends { title: string }>(item: T): T {
  console.log(item.title);
  return item;
}
const course = printTitle({
  id: 1,
  title: "TypeScript",
  free: true
});
console.log(course.free); // true

Nếu T không có ràng buộc, hàm không được giả định item có title. Extends ở đây yêu cầu T có ít nhất thuộc tính title kiểu string; nó không mang nghĩa kế thừa class tại thời điểm chạy. Trả lại T giúp giữ cả id và free trong kiểu kết quả, thay vì làm chúng biến mất khỏi thông tin mà người gọi nhìn thấy.

4. keyof và truy cập thuộc tính có kiểm soát

function getProperty<T, K extends keyof T>(item: T, key: K): T[K] {
  return item[key];
}
const title = getProperty(course, "title"); // string
const free = getProperty(course, "free"); // boolean
// getProperty(course, "price"); // Bỏ chú thích sẽ báo lỗi

Keyof T tạo một union các khóa của T. Ràng buộc K extends keyof T giới hạn key vào những khóa hợp lệ. T[K] là kiểu của thuộc tính tương ứng, nên lời gọi lấy title có kết quả string thay vì union của mọi kiểu thuộc tính. Đây là ví dụ nhỏ về kiểu đầu ra phụ thuộc vào đầu vào.

5. Khi nào nên dùng generics?

Dùng khi có một quan hệ kiểu cần được giữ: phần tử và mảng, khóa và object, hoặc dữ liệu và cấu trúc bao quanh. Nếu một hàm chỉ xử lý title và không cần trả lại thông tin của đầu vào, tham số { title: string } có thể đủ. Không cần thêm T vào mọi hàm để làm mã trông nâng cao.

Sau bài này, bạn có thể đọc lại Partial, Pick, Omit và Record trong phần kiểu dữ liệu 3: các ký hiệu trong dấu < > là tham số kiểu. Bước đầu chỉ cần dùng đúng chúng; conditional type và mapped type chuyên sâu có thể học sau. Để chạy các ví dụ cùng nhau, giữ thứ tự định nghĩa và thêm export {} ở cuối src/main.ts.

Đọc thêm: TypeScript: Generics.

Đọc thêm: TypeScript: keyof.

Đọc tiếp trong loạt bài

Bài trước: TypeScript cơ bản – Null, undefined, narrowing và type guards

Bài tiếp theo: TypeScript cơ bản – Module, import, export và tổ chức nhiều file

Xem chuyên mục TypeScript cơ bản

Bài viết liên quan:

TypeScript với Kiểu Dữ Liệu Cơ Bản – 3
TypeScript với Kiểu Dữ Liệu Cơ Bản – 2
TypeScript với Kiểu Dữ Liệu Cơ Bản – 1
Typescript cơ bản và cách cài đặt cho người mới

THÊM BÌNH LUẬN Cancel reply

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

TypeScript cơ bản – Class, constructor, phạm vi truy cập và implements

TypeScript cơ bản – Promise, async/await và kiểm tra dữ liệu API

TypeScript cơ bản – DOM, sự kiện và biểu mẫu trên trình duyệt

TypeScript cơ bản – Module, import, export và tổ chức nhiều file

TypeScript cơ bản – Generics và keyof: tái sử dụng mà vẫn giữ kiểu

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×