# TypeScript - Enums: Hướng dẫn dành cho người mới bắt đầu

Xin chào, các bạnfuture programmers! Hôm nay, chúng ta sẽ cùng lặn sâu vào thế giới kỳ diệu của TypeScript Enums. Đừng lo lắng nếu bạn chưa từng viết mã trước đây - tôi sẽ là người bạn thân thiện dẫn đường cho bạn trong hành trình này, giống như tôi đã làm cho biết bao sinh viên trong những năm dạy học của mình. Vậy, chúng ta cùng bắt đầu nào!

## Enums là gì?

Trước khi chúng ta nhảy vào các loại Enums khác nhau, hãy hiểu qua về chúng. Hãy tưởng tượng bạn đang sắp xếp tủ quần áo của mình. Bạn có thể có các danh mục khác nhau cho quần áo: áo, quần, giày, v.v. Enums trong TypeScript cũng giống như những danh mục đó - chúng giúp chúng ta nhóm các giá trị liên quan lại với nhau và đặt cho chúng những tên có ý nghĩa.

## Enums số

Enums số là loại Enums phổ biến nhất trong TypeScript. Chúng giống như việc gán số cho các siêu anh hùng yêu thích của bạn.

```typescript
enum Superheroes {
    Superman,
    Batman,
    WonderWoman,
    Flash
}

console.log(Superheroes.Superman);  // Output: 0
console.log(Superheroes.Batman);    // Output: 1
console.log(Superheroes.WonderWoman);  // Output: 2
console.log(Superheroes.Flash);     // Output: 3

Trong ví dụ này, TypeScript tự động gán số bắt đầu từ 0. Superman nhận được 0, Batman nhận được 1, và vân vân. Nó giống như họ đang xếp hàng cho một bức ảnh nhóm, và chúng ta đang cấp số theo vị trí của họ!

TypeScript - Enums

Nhưng nếu chúng ta muốn bắt đầu từ một số khác? Không có vấn đề! Chúng ta có thể làm được điều đó:

enum Villains {
    Joker = 1,
    LexLuthor,
    Cheetah,
    ReverseFlash
}

console.log(Villains.Joker);        // Output: 1
console.log(Villains.LexLuthor);    // Output: 2
console.log(Villains.Cheetah);      // Output: 3
console.log(Villains.ReverseFlash); // Output: 4

Ở đây, chúng ta đã bảo TypeScript bắt đầu đếm từ 1 cho Joker, và nó tự động tiếp tục từ đó cho các phần tử còn lại.

Enums chuỗi

Bây giờ, hãy设想 bạn không thích số và thích từ hơn. Đó là khi Enums chuỗi trở nên hữu ích. Chúng giống như việc đặt biệt danh cho thú cưng của bạn!

enum PetNames {
    Dog = "BUDDY",
    Cat = "WHISKERS",
    Fish = "BUBBLES",
    Bird = "TWEETY"
}

console.log(PetNames.Dog);   // Output: "BUDDY"
console.log(PetNames.Cat);   // Output: "WHISKERS"
console.log(PetNames.Fish);  // Output: "BUBBLES"
console.log(PetNames.Bird);  // Output: "TWEETY"

Với Enums chuỗi, chúng ta phải gán giá trị cho mỗi thành viên. Nó giống như đảm bảo mỗi thú cưng của bạn biết biệt danh đặc biệt của mình!

Enums hỗn hợp

Đôi khi, cuộc sống không chỉ là số hoặc chỉ là chuỗi - nó là sự pha trộn! Enums hỗn hợp giống như một hộp kẹo hỗn hợp - bạn có một chút mọi thứ.

enum MixedBag {
    Number = 1,
    String = "STRING",
    AnotherNumber = 2
}

console.log(MixedBag.Number);        // Output: 1
console.log(MixedBag.String);        // Output: "STRING"
console.log(MixedBag.AnotherNumber); // Output: 2

Mặc dù điều này có thể, nhưng thường được khuyến nghị nên chỉ sử dụng toàn bộ số hoặc toàn bộ chuỗi trong một Enum để duy trì sự nhất quán.

Enums tại thời điểm chạy

Một điều tuyệt vời về Enums là chúng tồn tại tại thời điểm chạy. Điều này có nghĩa là bạn có thể sử dụng chúng trong mã của mình như bất kỳ đối tượng nào khác!

enum Fruits {
    Apple,
    Banana,
    Orange
}

function getFruitName(fruit: Fruits): string {
    return Fruits[fruit];
}

console.log(getFruitName(Fruits.Apple));  // Output: "Apple"
console.log(getFruitName(Fruits.Banana)); // Output: "Banana"

Ở đây, chúng ta đang sử dụng Enum như nếu nó là một đối tượng JavaScript thông thường. Nó giống như có một từ điển ma thuật có thể dịch số thành tên trái cây!

Enums tại thời điểm biên dịch

Enums cũng tỏa sáng tại thời điểm biên dịch. Chúng giúp TypeScript bắt lỗi trước khi mã của bạn thậm chí chạy!

enum DaysOfWeek {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

let day: DaysOfWeek = DaysOfWeek.Monday;
day = DaysOfWeek.Friday;  // Điều này không sao

// day = "Monday";  // Lỗi: Type '"Monday"' is not assignable to type 'DaysOfWeek'.

TypeScript sẽ cho bạn biết nếu bạn cố gắng gán một giá trị không phải là phần của Enum. Nó giống như có một bảo vệ严格的 câu lạc bộ chỉ cho vào các ngày trong tuần!

Enums Ambient

Enums Ambient là một chút đặc biệt. Chúng được sử dụng khi bạn đang nói với TypeScript về các Enums tồn tại ở nơi khác trong mã của bạn hoặc trong thư viện bạn đang sử dụng.

declare enum ExternalEnum {
    A = 1,
    B,
    C = 2
}

Từ khóa declare giống như nói, "Hey TypeScript, tin tôi đi, Enum này tồn tại ở nơi khác trong mã." Nó rất hữu ích khi bạn làm việc với mã không được viết bằng TypeScript.

Đối tượng vs. Enums

Bạn có thể tự hỏi, "Tại sao không chỉ sử dụng đối tượng?" Well, Enums có một số ưu thế:

// Sử dụng đối tượng
const ColorObject = {
    Red: 'RED',
    Green: 'GREEN',
    Blue: 'BLUE'
} as const;

// Sử dụng Enum
enum ColorEnum {
    Red = 'RED',
    Green = 'GREEN',
    Blue = 'BLUE'
}

// Với đối tượng, bạn cần sử dụng khẳng định 类型
let objColor: keyof typeof ColorObject = 'Red';

// Với Enums, nó đơn giản hơn
let enumColor: ColorEnum = ColorEnum.Red;

Enums cung cấp tính an toàn 类型 tốt hơn và thường ngắn gọn hơn trong nhiều trường hợp.

Sử dụng Enum làm tham số hàm

Enums rất tốt cho tham số hàm. Chúng làm cho mã của bạn dễ đọc hơn và ngăn ngừa lỗi:

enum Sizes {
    Small,
    Medium,
    Large
}

function orderCoffee(size: Sizes): string {
    switch(size) {
        case Sizes.Small:
            return "Here's your small coffee!";
        case Sizes.Medium:
            return "One medium coffee coming right up!";
        case Sizes.Large:
            return "Large coffee, extra caffeine!";
        default:
            return "We don't have that size!";
    }
}

console.log(orderCoffee(Sizes.Medium));  // Output: "One medium coffee coming right up!"
// console.log(orderCoffee("Venti"));    // Lỗi: Argument of type '"Venti"' is not assignable to parameter of type 'Sizes'.

Bằng cách sử dụng Enum cho tham số kích thước, chúng ta đảm bảo rằng chỉ có các kích thước hợp lệ có thể được truyền vào hàm. Nó giống như có một thực đơn với các tùy chọn cố định - không có sự nhầm lẫn về kích thước nào có sẵn!

Phương thức Enums

Dưới đây là bảng các phương thức hữu ích để làm việc với Enums:

Phương thức Mô tả Ví dụ
Object.keys() Lấy tất cả các khóa của một Enum Object.keys(Sizes)
Object.values() Lấy tất cả các giá trị của một Enum Object.values(Sizes)
Object.entries() Lấy các cặp khóa-giá trị của một Enum Object.entries(Sizes)
Enum[key] Lấy giá trị cho một khóa Sizes[Sizes.Small]
Enum[value] Lấy khóa cho một giá trị (cho Enums số) Sizes[0]

Những phương thức này giúp bạn làm việc với Enums theo nhiều cách khác nhau, như lấy tất cả các kích thước khả dụng hoặc tìm tên của một kích thước từ giá trị của nó.

Và thế là bạn đã bước những bước đầu tiên vào thế giới của TypeScript Enums. Nhớ rằng, lập trình giống như học một ngôn ngữ mới - nó đòi hỏi sự gyak, nhưng sớm bạn sẽ thành thạo trong Enum-speak! Hãy tiếp tục mã hóa, giữ sự tò mò, và đừng quên vui vẻ trên đường đi. Ai biết được, có lẽ bạn sẽ tạo ra một Enum cho các hương vị kem yêu thích của mình tiếp theo!

Credits: Image by storyset