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

Tìm hiểu về utility types trong Typescript

TypeScript cung cấp cho ta một loạt các "Utility Types" (kiểu dữ liệu tiện ích) mạnh mẽ, giúp mình thao tác và biến đổi kiểu dữ liệu dễ dàng. Trong bài viết này, mình sẽ tìm hiểu về hai trong số những loại Utility Types phổ biến nhất: Pick và Omit.

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.

Cả hai Pick và Omit đều cho phép bạn tùy chỉnh kiểu dữ liệu hiện có một cách dễ dàng bằng cách chọn hoặc loại bỏ các thuộc tính cụ thể. Chúng là một phần quan trọng của TypeScript và giúp bạn viết mã nguồn sạch sẽ, quản lý dự án dễ dàng hơn và tăng tính bảo mật trong mã nguồn TypeScript của bạn. Hãy cùng tìm hiểu về chúng và cách chúng có thể được áp dụng trong các tình huống thực tế.

Utility Types là gì?

images 20 1  jpg

Utility Types là một tập hợp các kiểu dữ liệu tiện ích được xây dựng sẵn trong TypeScript để giúp bạn tạo, biến đổi và thao tác với kiểu dữ liệu một cách hiệu quả. Các kiểu dữ liệu này giúp bạn tránh việc phải viết mã nguồn thừa và làm cho mã nguồn TypeScript trở nên sạch sẽ, dễ quản lý hơn.

Một số Utility Types phổ biến trong TypeScript bao gồm:

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

  • Partial<T>: Cho phép bạn tạo một kiểu dữ liệu mới bằng việc thêm tính năng tùy chọn (optional properties) vào kiểu dữ liệu hiện có.

  • Required<T>: Ngược lại với Partial, Required loại bỏ tất cả tính năng tùy chọn khỏi một kiểu dữ liệu.

  • Readonly<T>: Biến đổi một kiểu dữ liệu bằng cách làm cho tất cả các thuộc tính trở thành thuộc tính chỉ đọc.

  • Record<K, T>: Tạo một kiểu dữ liệu với các thuộc tính được định nghĩa bởi một danh sách khóa K và mỗi thuộc tính có kiểu T.

  • Pick<T, K>: Lấy một phần của kiểu dữ liệu T chỉ bằng cách chọn các thuộc tính có tên nằm trong danh sách khóa K.

  • Omit<T, K>: Tạo một kiểu dữ liệu mới bằng cách loại bỏ các thuộc tính có tên nằm trong danh sách khóa K khỏi kiểu dữ liệu T.

Các Utility Types này giúp bạn viết mã nguồn TypeScript một cách ngắn gọn, tạo ra các kiểu dữ liệu một cách dễ dàng và đảm bảo tính toàn vẹn và an toàn của kiểu dữ liệu trong dự án của bạn.

Tại sao cần Utility Types?

Sử dụng Utility Types mang lại nhiều lợi ích quan trọng cho phát triển ứng dụng TypeScript:

  • Tùy chỉnh kiểu dữ liệu: Utility Types cho phép bạn tùy chỉnh kiểu dữ liệu hiện có dễ dàng hơn. Bạn có thể lựa chọn thuộc tính cần thiết hoặc loại bỏ các thuộc tính không mong muốn.
  • Tăng tính bảo mật: Việc sử dụng Utility Types giúp kiểm tra kiểu dữ liệu tại thời điểm biên dịch, giảm thiểu lỗi thời gian chạy và tăng tính bảo mật của mã nguồn.
  • Tái sử dụng mã nguồn: Utility Types giúp bạn viết mã nguồn tái sử dụng hơn, vì bạn có thể xây dựng các kiểu dữ liệu chung cho nhiều phần của mã nguồn.

Với sự giúp đỡ của Utility Types, bạn có thể nắm vững kiểu dữ liệu trong TypeScript và viết mã nguồn TypeScript một cách hiệu quả và linh hoạt.

Utility Types phổ biến

Trong phần này, mình sẽ tìm hiểu về hai Utility Types phổ biến là Pick<T, K> và Omit<T, K>, và cách chúng có thể được sử dụng để tạo và biến đổi kiểu dữ liệu trong TypeScript.

Pick<T, K>

Định nghĩa và cách sử dụng Pick:

  • Pick<T, K> là một Utility Type cho phép bạn tạo một kiểu dữ liệu mới bằng cách chọn một tập hợp các thuộc tính từ kiểu dữ liệu T dựa trên danh sách khóa K.
  • Ví dụ: Pick<User, 'name' | 'email'> sẽ tạo ra một kiểu dữ liệu mới chỉ chứa thuộc tính 'name' và 'email' từ kiểu dữ liệu User.

Ví dụ minh họa:

type User = {
    name: string;
    age: number;
    email: string;
    address: string;
};

type UserProfile = Pick<User, 'name' | 'email'>;

const user: UserProfile = {
    name: 'John Doe',
    email: 'john@example.com',
};

Omit<T, K>

Định nghĩa và cách sử dụng Omit:

  • Omit<T, K> là một Utility Type cho phép bạn tạo một kiểu dữ liệu mới bằng cách loại bỏ một tập hợp các thuộc tính từ kiểu dữ liệu T dựa trên danh sách khóa K.
  • Ví dụ: Omit<User, 'age' | 'address'> sẽ tạo ra một kiểu dữ liệu mới không chứa thuộc tính 'age' và 'address' từ kiểu dữ liệu User.

Ví dụ minh họa:

type User = {
    name: string;
    age: number;
    email: string;
    address: string;
};

type PublicProfile = Omit<User, 'age' | 'address'>;

const user: PublicProfile = {
    name: 'John Doe',
    email: 'john@example.com',
};

Các Utility Types như Pick và Omit giúp bạn quản lý và biến đổi kiểu dữ liệu một cách hiệu quả trong TypeScript, đặc biệt khi bạn chỉ muốn làm việc với một phần của kiểu dữ liệu mà không cần sao chép toàn bộ kiểu.

Một số utility types khác

Trong TypeScript, ngoài Pick và Omit, còn có một số utility types khác mà bạn có thể sử dụng để tạo và biến đổi kiểu dữ liệu một cách linh hoạt.

Partial<T> - Tạo kiểu dữ liệu với các thuộc tính có thể thiếu

Utility type Partial cho phép bạn tạo một kiểu dữ liệu mới dựa trên một kiểu hiện có, nhưng tất cả các thuộc tính trong kiểu mới có thể bị thiếu (undefined).

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type PartialTodo = Partial<Todo>;

const incompleteTodo: PartialTodo = {
  title: 'Learn TypeScript',
};

Readonly<T> - Tạo kiểu dữ liệu chỉ đọc

Utility type Readonly biến đổi một kiểu dữ liệu hiện có thành kiểu dữ liệu chỉ đọc, tức là bạn không thể thay đổi giá trị của các thuộc tính.

interface Point {
  x: number;
  y: number;
}

type ImmutablePoint = Readonly<Point>;

const point: ImmutablePoint = { x: 1, y: 2 };
point.x = 3; // Lỗi: Không thể gán lại giá trị x.

Record<K, T> - Tạo kiểu dữ liệu dựa trên các khóa

Utility type Record cho phép bạn tạo một kiểu dữ liệu mà mỗi thuộc tính trong đó có kiểu dữ liệu giống nhau và tương ứng với các khóa trong kiểu K.

type Weekdays = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday';

type WeeklySchedule = Record<Weekdays, string>;

const schedule: WeeklySchedule = {
  Monday: 'Work',
  Tuesday: 'Gym',
  Wednesday: 'Meetings',
  // ...
};

Required<T> - Tạo kiểu dữ liệu yêu cầu tất cả thuộc tính

Utility type Required biến đổi một kiểu dữ liệu hiện có thành kiểu dữ liệu yêu cầu tất cả thuộc tính phải được định nghĩa.

interface Config {
  width?: number;
  height?: number;
}

type RequiredConfig = Required<Config>;

const fullConfig: RequiredConfig = {
  width: 800,
  height: 600,
};

NonNullable<T> - Loại bỏ các giá trị null và undefined

Utility type NonNullable biến đổi kiểu dữ liệu hiện có thành kiểu dữ liệu loại bỏ giá trị null và undefined.

type NullableString = string | null | undefined;
type NonNullString = NonNullable<NullableString>;

const str: NonNullString = 'Hello, TypeScript!';

Những utility types này giúp bạn tùy chỉnh và biến đổi kiểu dữ liệu một cách dễ dàng trong TypeScript, tạo ra tính linh hoạt và hiệu quả trong việc quản lý kiểu dữ liệu.

Tùy chỉnh utility types

Tạo utility types tùy chỉnh

Trong TypeScript, bạn có thể tạo utility types tùy chỉnh của riêng mình để đáp ứng nhu cầu cụ thể của dự án. Điều này giúp bạn mở rộng tính năng kiểu dữ liệu của TypeScript theo cách linh hoạt và hiệu quả. Dưới đây là một ví dụ đơn giản về cách tạo một utility type tùy chỉnh:

type MyUtilityType<T> = {
  data: T;
  timestamp: number;
};

const customData: MyUtilityType<string> = {
  data: 'Hello, TypeScript!',
  timestamp: Date.now(),
};

Trong ví dụ này, MyUtilityType là một utility type tùy chỉnh với một kiểu dữ liệu generics T. Nó tạo ra một kiểu dữ liệu mới với hai thuộc tính: data có kiểu dữ liệu T và timestamp có kiểu dữ liệu number.

Lợi ích và hạn chế của sử dụng utility types

Giúp kiểm tra kiểu dữ liệu

Sử dụng utility types giúp kiểm tra và đảm bảo tính chính xác của kiểu dữ liệu trong mã nguồn TypeScript. Điều này giúp bạn phát hiện và tránh lỗi kiểu dữ liệu trước khi chương trình chạy.

Tăng cường tính bảo mật

Một số utility types như Readonly và Partial giúp bạn tăng cường tính bảo mật bằng cách giới hạn quyền truy cập và sửa đổi đối tượng. Điều này giúp ngăn chặn các lỗi trong quá trình phát triển.

Tái sử dụng mã nguồn

Sử dụng utility types cho phép tái sử dụng mã nguồn và kiểu dữ liệu trong các phần khác nhau của dự án. Điều này giúp giảm sự lặp lại trong mã nguồn và làm cho mã nguồn dễ bảo trì hơn.

Hạn chế

Không phải lúc nào cũng thích hợp

Utility types không phải lúc nào cũng thích hợp cho mọi tình huống. Việc lựa chọn phù hợp giữa sử dụng utility types và viết mã kiểu dữ liệu thủ công phụ thuộc vào yêu cầu cụ thể của dự án.

Không thể thay đổi kiểu dữ liệu tự động

Utility types giúp bạn tạo ra các biến thể mới của kiểu dữ liệu hiện có, nhưng chúng không thay đổi kiểu dữ liệu gốc một cách tự động. Điều này có nghĩa rằng bạn cần sử dụng kiểu biến thể mới thay vì cập nhật kiểu gốc.

Ví dụ minh họa

Sử dụng Pick và Omit trong thực tế

Để hiểu rõ hơn về cách sử dụng Pick và Omit trong các tình huống thực tế, mình hãy xem xét một số ví dụ cụ thể:

Sử dụng Pick để lựa chọn các thuộc tính từ một đối tượng:

interface Person {
  name: string;
  age: number;
  address: string;
}

type PersonNameAndAge = Pick<Person, 'name' | 'age'>;

const personInfo: PersonNameAndAge = {
  name: 'John',
  age: 30,
};

Trong ví dụ này, mình sử dụng Pick để lựa chọn chỉ thuộc tính 'name' và 'age' từ kiểu Person, tạo ra kiểu mới PersonNameAndAge.

Sử dụng Omit để loại bỏ các thuộc tính từ một đối tượng:

interface Car {
  make: string;
  model: string;
  year: number;
  color: string;
}

type CarWithoutColor = Omit<Car, 'color'>;

const carInfo: CarWithoutColor = {
  make: 'Toyota',
  model: 'Camry',
  year: 2022,
};

Ở đây, mình sử dụng Omit để loại bỏ thuộc tính 'color' khỏi kiểu Car, tạo ra kiểu CarWithoutColor.

Những ví dụ này cho thấy cách Pick và Omit có thể giúp bạn quản lý kiểu dữ liệu một cách hiệu quả trong TypeScript. Chúng giúp bạn tạo ra kiểu dữ liệu mới dựa trên kiểu hiện có, giúp tăng tính bảo mật và tái sử dụng mã nguồn.

Kết bài

Trong bài viết này, mình đã tìm hiểu về utility types trong TypeScript và cách chúng có thể cải thiện tính hiệu quả, tính bảo mật và tái sử dụng mã nguồn trong dự án của bạn. Utility types cung cấp một tập hợp các kiểu dữ liệu tùy chỉnh có sẵn sẽ giúp bạn kiểm tra, bảo vệ kiểu dữ liệu và sáng tạo kiểu dữ liệu mới.

Mình đã tìm hiểu về các utility types phổ biến như Pick, Omit, Partial, Readonly, Record, Required, NonNullable và cách sử dụng chúng để giải quyết các tình huống thực tế.

Mình cũng đã xem xét việc tạo utility types tùy chỉnh và lợi ích của việc sử dụng chúng trong việc kiểm tra kiểu dữ liệu, tăng cường tính bảo mật và tái sử dụng mã nguồn.

Tuy nhiên, mình cũng đã nhắc đến hạn chế của utility types, bao gồm việc chọn lựa giữa sử dụng utility types và viết mã kiểu dữ liệu thủ công theo yêu cầu cụ thể của dự án.

Trong tổng quan, utility types là một công cụ mạnh mẽ cho các nhà phát triển TypeScript để làm cho mã nguồn của họ dễ bảo trì và hiệu quả hơn. Hy vọng rằng sau bài viết này, bạn có thêm hiểu biết về cách sử dụng chúng trong dự án của mình.

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

Mapped Types trong TypeScript

Mapped Types 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

Top