TYPESCRIPT 2.X CĂN BẢN
Hàm trong TypeScript Sử dụng hàm generics Sử dụng hàm generics trong TypeScript Sử dụng Array trong TypeScript Sử dụng Tuple trong TypeScript Sử dụng kiểu Array, Tuple, Enum trong TypeScript Interface trong Typescript Hybrid Types với Interface trong TypeScript Khác biệt khi sử dụng 'type' và 'interface' trong TypeScript Cách dùng Enum trong TypeScript Types và interface trong TypeScript Class trong TypeScript Sử dụng Abstract Classes trong TypeScript Sử dụng Interface trong Typescript (phần 2) Sử dụng Casting trong TypeScript Tìm hiểu về Generics trong TypeScript Tìm hiểu về utility types trong Typescript Utility types phổ biến trong Typescript Sử dụng default parameters trong TypeScript Modules trong TypeScript Rest Parameters trong TypeScript Sử dụng Function Overloadings trong TypeScript Sử dụng Type Assertions trong TypeScript Sử dụng Static Methods và Properties trong TypeScript. Sử dụng Access Modifiers trong TypeScript 10 mẹo và thủ thuật hay nhất trong TypeScript 5 Cách giúp bạn loại bỏ "any" trong TypeScript Mapped Types trong TypeScript Dependency Injection trong Typescript 5 ký hiệu khó hiểu cần biết trong TypeScript Cách sử dụng @ts-expect-error trong Typescript Declaration Merging trong TypeScript Tìm hiểu Branded Type trong TypeScript Namespaces trong Typescript Phân biệt Modules và Namespaces trong TypeScript Triple-Slash Directives trong TypeScript là gì? Phần 1: Biến trong TypeScript Phần 2: Biến trong TypeScript Property trong TypeScript Phân tích JSON trong TypeScript Bài tập TypeScript: Các dạng bài tập cơ bản Bài tập TypeScript: Lập trình Hướng đối tượng trong TypeScript Bài tập TypeScript: Kiểu Generic Types trong Typescript Bài tập TypeScript: Các kiểu dữ liệu mảng và tuple. Bài tập TypeScript: Classes và Inheritance trong Typescript Bài 01: TypeScript là gì? TypeScript và Javascript Bài 02: Cài đặt TypeScript Bài 03: TypeScript Basic Types Bài 04: Khai báo biến trong TypeScript Bài 05: Lệnh If Else và Switch Case trong TypeScript Bài 06: Vòng lặp trong TypeScript
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Mapped Types trong TypeScript

Trong bài viết này, mình sẽ tìm hiểu "Mapped Types" trong TypeScript, một tính năng cho phép bạn tạo ra các kiểu dữ liệu mới dựa trên các kiểu dữ liệu tồn tại.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Mapped Types cho phép bạn ánh xạ qua các thành phần của kiểu dữ liệu gốc và thay đổi chúng theo cách cụ thể. Chúng có thể được sử dụng để tạo các phiên bản mới của kiểu dữ liệu, tạo các thuộc tính tùy chọn, các thuộc tính chỉ đọc và thậm chí tạo các kiểu dữ liệu tổng quát. Hãy cùng tìm hiểu sâu hơn về Mapped Types trong TypeScript và cách chúng giúp làm cho mã nguồn của bạn mạnh mẽ hơn.

Mapped Types là gì?

t E1 BA A3i 20xu E1 BB 91ng 20 2  jpg

Mapped Types là một tính năng trong TypeScript cho phép bạn tạo ra các kiểu dữ liệu mới dựa trên các kiểu dữ liệu tồn tại. Thông qua Mapped Types, bạn có khả năng ánh xạ qua các thành phần của một kiểu dữ liệu gốc (base type) và thay đổi chúng theo cách cụ thể để tạo ra một phiên bản mới của kiểu dữ liệu.

Bài viết này được đăng tại [free tuts .net]

Mapped Types cho phép bạn thực hiện các thay đổi như thêm thuộc tính tùy chọn (optional properties), thay đổi kiểu của các thuộc tính, tạo ra các phiên bản chỉ đọc (readonly properties), và nhiều tính năng khác một cách linh hoạt. Điều này giúp bạn tạo ra các kiểu dữ liệu mới dựa trên cấu trúc của các kiểu dữ liệu hiện có mà không cần phải viết lại mã nhiều lần.

Mapped Types thường được sử dụng trong các tình huống cần tạo ra các kiểu dữ liệu tổng quát (generic types) hoặc khi bạn muốn biến đổi kiểu dữ liệu một cách động và linh hoạt. Chúng giúp đảm bảo tính toàn vẹn của mã nguồn và kiểm tra kiểu tại thời điểm biên dịch, giúp bạn viết mã TypeScript an toàn và hiệu quả hơn.

Các toán tử keyof và keyof typeof

Trong TypeScript, các toán tử keyof và keyof typeof được sử dụng để truy cập các khóa (keys) của kiểu dữ liệu gốc và cho phép bạn ánh xạ qua các thành phần của kiểu dữ liệu. Hãy cùng tìm hiểu chi tiết về chúng và so sánh cách chúng hoạt động.

Keyof

Toán tử keyof cho phép bạn truy cập các khóa (keys) của một kiểu dữ liệu gốc (base type). Điều này có nghĩa rằng bạn có thể sử dụng keyof để lặp qua các khóa của một đối tượng hoặc truy cập các tên của các thuộc tính của một kiểu dữ liệu.

Ví dụ:

type Person = {
    name: string;
    age: number;
};

type PersonKeys = keyof Person; // PersonKeys sẽ là 'name' | 'age'

Trong ví dụ trên, keyof Person trả về một kiểu dữ liệu mới chứa các khóa của kiểu dữ liệu Person, nghĩa là 'name' và 'age'.

Keyof typeof

Toán tử keyof typeof cũng truy cập các khóa (keys) của một kiểu dữ liệu gốc, tuy nhiên, nó hoạt động với một biến hoặc một đối tượng cụ thể, không phải là kiểu dữ liệu cụ thể.

Ví dụ:

const person = {
    name: "Alice",
    age: 30,
};

type PersonKeys = keyof typeof person; // PersonKeys s

Tạo kiểu dữ liệu mới với Mapped Types

Mapped Types cho phép bạn tạo kiểu dữ liệu mới bằng cách ánh xạ qua các thành phần của kiểu dữ liệu gốc và thay đổi chúng theo cách cụ thể. Dưới đây, mình sẽ xem xét một số ví dụ về cách tạo kiểu dữ liệu mới bằng Mapped Types:

Optional Properties (Thuộc tính tùy chọn)

Một trong những cách phổ biến sử dụng Mapped Types là tạo các thuộc tính tùy chọn trong kiểu dữ liệu. Điều này thường được thực hiện bằng cách thêm dấu hỏi (?) vào cuối của mỗi thuộc tính. Mapped Types giúp bạn thực hiện điều này một cách tự động.

Ví dụ:

type Person = {
    name: string;
    age: number;
};

type PersonWithOptional = {
    [K in keyof Person]?: Person[K];
};

const alice: PersonWithOptional = {}; // Thuộc tính name và age đều là tùy chọn

Trong ví dụ trên, Mapped Type PersonWithOptional đã biến đổi kiểu dữ liệu Person bằng cách thêm dấu hỏi (?) vào cuối mỗi thuộc tính, tạo ra các thuộc tính tùy chọn.

Readonly Properties (Thuộc tính chỉ đọc)

Mapped Types cũng cho phép bạn tạo kiểu dữ liệu với các thuộc tính chỉ đọc bằng cách sử dụng readonly. Điều này đảm bảo rằng các thuộc tính không thể thay đổi sau khi được gán giá trị ban đầu.

Ví dụ:

type Person = {
    name: string;
    age: number;
};

type ReadonlyPerson = {
    readonly [K in keyof Person]: Person[K];
};

const bob: ReadonlyPerson = { name: "Bob", age: 25 };
// Không thể thay đổi giá trị của thuộc tính name và age sau khi đã được gán giá trị

Partial Types (Kiểu dữ liệu con)

Mapped Types cũng cho phép bạn tạo ra kiểu dữ liệu con (partial types) bằng cách thêm dấu hỏi (?) vào cuối mỗi thuộc tính. Điều này có nghĩa rằng không cần phải khai báo tất cả các thuộc tính mà chỉ cần khai báo những thuộc tính cần thiết.

Ví dụ:

type Person = {
    name: string;
    age: number;
};

type PartialPerson = {
    [K in keyof Person]?: Person[K];
};

const carol: PartialPerson = { name: "Carol" };
// Chỉ cần khai báo thuộc tính name, age là tùy chọn

Trong ví dụ trên, Mapped Type PartialPerson đã tạo ra một kiểu dữ liệu con cho phép chỉ cần khai báo thuộc tính name, và age sẽ là tùy chọn.

Sử dụng Mapped Types với Generic Types

Mapped Types và Generic Types có thể kết hợp để tạo kiểu dữ liệu tổng quát (generic type) có tính linh hoạt cao. Điều này cho phép bạn sử dụng Mapped Types trong nhiều tình huống và với nhiều kiểu dữ liệu khác nhau. Hãy cùng tìm hiểu cách kết hợp chúng và cách chúng hoạt động.

Kết hợp Mapped Types và Generic Types

Khi kết hợp Mapped Types và Generic Types, bạn có khả năng tạo ra các kiểu dữ liệu tổng quát cho bất kỳ kiểu dữ liệu nào mà bạn chọn. Điều này rất hữu ích khi bạn muốn tạo ra các kiểu dữ liệu hoặc biến đổi kiểu dữ liệu dựa trên một kiểu dữ liệu gốc.

Ví dụ:

type ValueOrArray<T> = T | T[];

type OptionalProperties<T> = {
    [K in keyof T]?: T[K];
};

const nameOrNames: ValueOrArray<string> = "Alice";
const person: OptionalProperties<{ name: string; age: number }> = { name: "Bob" };

Trong ví dụ trên, ValueOrArray OptionalProperties là hai kiểu dữ liệu tổng quát được tạo bằng cách kết hợp Generic Types Mapped Types. ValueOrArray cho phép bạn tạo kiểu dữ liệu tổng quát cho các giá trị hoặc mảng chứa các giá trị. OptionalProperties cho phép bạn tạo kiểu dữ liệu tổng quát với các thuộc tính tùy chọn dựa trên một kiểu dữ liệu gốc.

Kết hợp Mapped Types và Generic Types là một cách mạnh mẽ để tạo kiểu dữ liệu tổng quát và biến đổi kiểu dữ liệu dựa trên nhu cầu cụ thể của bạn.

Ứng dụng thực tế

Mapped Types là một tính năng mạnh mẽ trong TypeScript, và chúng rất hữu ích khi viết mã cho các thư viện (library) và frameworks trong TypeScript. Dưới đây, mình sẽ thảo luận về tại sao Mapped Types quan trọng trong việc phát triển thư viện và cung cấp một ví dụ cụ thể về cách chúng có thể được sử dụng trong thực tế.

Sử dụng Mapped Types trong TypeScript Library

  • Bảo đảm tính toàn vẹn: Khi bạn viết một thư viện TypeScript, đặc biệt là khi bạn định nghĩa các giao diện (interfaces) cho người sử dụng, bạn muốn đảm bảo tính toàn vẹn của các kiểu dữ liệu mà thư viện của bạn định nghĩa. Mapped Types giúp bạn định nghĩa các giao diện tự động dựa trên các giao diện gốc, đảm bảo rằng người sử dụng thư viện phải tuân theo các quy tắc kiểu dữ liệu cụ thể.

  • Tính linh hoạt: Mapped Types cho phép bạn tạo ra các biến thể của các giao diện cơ bản, giúp thích nghi với nhu cầu cụ thể của người sử dụng. Điều này giúp thư viện của bạn trở nên linh hoạt và có khả năng tùy chỉnh cao.

Ví dụ sau đây sẽ minh họa cách bạn có thể sử dụng Mapped Types trong một thư viện TypeScript để tạo các giao diện cụ thể:

type User = {
    id: string;
    name: string;
    email: string;
};

type Admin = {
    id: string;
    name: string;
    role: "admin";
};

type Moderator = {
    id: string;
    name: string;
    role: "moderator";
};

type UserRoles = "user" | "admin" | "moderator";

type UserWithRole<T extends UserRoles> = {
    [K in keyof User]: K extends "id" ? User[K] : T extends "user" ? User[K] : T extends "admin" ? Admin[K] : T extends "moderator" ? Moderator[K] : never;
};

const user: UserWithRole<"user"> = {
    id: "123",
    name: "Alice",
    email: "alice@example.com",
};

const admin: UserWithRole<"admin"> = {
    id: "456",
    name: "Bob",
    role: "admin",
};

Trong ví dụ này, Mapped Types được sử dụng để tạo ra các biến thể của giao diện User dựa trên các vai trò người dùng (user roles) như "user," "admin," và "moderator." Điều này cho phép bạn định nghĩa các kiểu dữ liệu cụ thể cho từng vai trò mà thư viện của bạn hỗ trợ.

Kết bài

Mapped Types trong TypeScript là một tính năng mạnh mẽ và đa dạng, giúp bạn tạo kiểu dữ liệu mới, biến đổi kiểu dữ liệu tồn tại và đảm bảo tính toàn vẹn của mã nguồn. Trong bài viết này, mình đã tìm hiểu cách Mapped Types cho phép bạn thao tác với các thuộc tính của kiểu dữ liệu gốc, tạo các thuộc tính tùy chọn, chỉ đọc, và thậm chí tạo kiểu dữ liệu tổng quát.

Mapped Types không chỉ hữu ích trong việc viết mã ứng dụng thông thường mà còn trong việc phát triển các thư viện và frameworks TypeScript. Chúng giúp bạn đảm bảo tính toàn vẹn của các kiểu dữ liệu, tạo các biến thể linh hoạt, và cung cấp một cách mạnh mẽ để thích nghi với nhu cầu cụ thể của dự án.

Việc hiểu và sử dụng Mapped Types có thể giúp bạn viết mã TypeScript hiệu quả hơn và quản lý kiểu dữ liệu một cách thông minh. Hãy tận dụng tính năng này để cải thiện chất lượng và sự bảo trì của mã nguồn của bạn.

Cùng chuyên mục:

Bài tập TypeScript: Classes và Inheritance trong Typescript

Bài tập TypeScript: Classes và Inheritance trong Typescript

Bài tập TypeScript: Các kiểu dữ liệu mảng và tuple.

Bài tập TypeScript: Các kiểu dữ liệu mảng và tuple.

Bài tập TypeScript: Kiểu Generic Types trong Typescript

Bài tập TypeScript: Kiểu Generic Types trong Typescript

Bài tập TypeScript: Lập trình Hướng đối tượng trong TypeScript

Bài tập TypeScript: Lập trình Hướng đối tượng trong TypeScript

Bài tập TypeScript: Các dạng bài tập cơ bản

Bài tập TypeScript: Các dạng bài tập cơ bản

Phân tích JSON trong TypeScript

Phân tích JSON trong TypeScript

Property trong TypeScript

Property trong TypeScript

Phần 2: Biến trong TypeScript

Phần 2: Biến trong TypeScript

Phần 1: Biến trong TypeScript

Phần 1: Biến trong TypeScript

Triple-Slash Directives trong TypeScript là gì?

Triple-Slash Directives trong TypeScript là gì?

Phân biệt Modules và Namespaces trong TypeScript

Phân biệt Modules và Namespaces trong TypeScript

Tìm hiểu Branded Type trong TypeScript

Tìm hiểu Branded Type trong TypeScript

Namespaces trong Typescript

Namespaces trong Typescript

Declaration Merging trong TypeScript

Declaration Merging trong TypeScript

Cách sử dụng @ts-expect-error trong typescript

Cách sử dụng @ts-expect-error trong typescript

5 ký hiệu khó hiểu cần biết trong TypeScript

5 ký hiệu khó hiểu cần biết trong TypeScript

Dependency Injection trong Typescript

Dependency Injection trong Typescript

5 Cách giúp bạn loại bỏ

5 Cách giúp bạn loại bỏ "any" trong TypeScript

10 mẹo và thủ thuật hay nhất trong TypeScript

10 mẹo và thủ thuật hay nhất trong TypeScript

Sử dụng Access Modifiers trong TypeScript

Sử dụng Access Modifiers trong TypeScript

Top