Khi sử dụng TypeScript, chúng ta thường gặp phải trường hợp xác định kiểu của một biến mà giá trị của nó rơi vào một hay nhiều khả năng khác nhau.
Ví dụ, status của một button có thể là: "hidden"
, "enabled"
, "disabled"
.
Với Typescript chúng ta có ít nhất hai cách
// Kiểu string enums
export enum ButtonStatus {
HIDDEN = 'HIDDEN',
ENABLED = 'ENABLED',
DISABLED = 'DISABLED',
};
// Kiểu string literal union types
type ButtonStatus = 'HIDDEN' | 'ENABLED' | 'DISABLED';
Có cũng có kiểu enum cơ bản (không có phần = 'HIDDEN'
), khi đó các giá trị sẽ chạy từ 0 → 2, nhưng ta sẽ không bàn về nó trong bài viết so sánh này.
Nào, hãy bắt đầu so sánh coi 🥰
Declaring & Accessing
- Tính ngắn gọn trong khai báo
- [✔] Union Type
- [✘] String Enums
- Autocompletion trên Editor/IDE
- [✔] Union Type
- Tự động nhận trên VsCode
- [✘] String Enums
- Cần exported và imported mới hoạt động
- [✔] Union Type
Chiến thắng với 2 points cho Union types!
Union Type | String Enums |
---|---|
2 | 0 |
Extending
- [✔] Union Type
type DynamicButtonStatus = ButtonStatus | 'LOADING';
- [✘] String Enums
- Sử dụng trick spread operator
export enum ButtonStatus { HIDDEN = 'HIDDEN', ENABLED = 'ENABLED', DISABLED = 'DISABLED', }; // extend enum using "spread" const NewButtonStatus = { ...ButtonStatus, SHOW: 'SHOW', BLINK: 'BLINK' };
- Sử dụng trick spread operator
Thêm 1 point cho Union types!
Union Type | String Enums |
---|---|
3 | 0 |
TypeError
- [✔] Union Type
-
Playground Link
// With union types of string literals type ButtonStatus = 'HIDDEN' | 'ENABLED' | 'DISABLED'; function TestUnionType(status: ButtonStatus) { switch (status) { case 'HIDDEN': return 1; case 'ENABLED': return 2; case 'DISABLED': return 3; // Notice that there's no default case } } // Compile success if pass valid status with Union Type console.log(TestUnionType('HIDDEN')); // Compile error if pass invalid status with Union Type console.log(TestUnionType('SHOW'));
- Error được phát hiện từ bước Transpile
Argument of type '"SHOW"' is not assignable to parameter of type 'ButtonStatus'.
-
Playground Link
- [✘] String Enums
-
Playground Link
// With string enums enum ButtonStatus { HIDDEN = 'HIDDEN', ENABLED = 'ENABLED', DISABLED = 'DISABLED' }; function TestStringEnums(status: ButtonStatus) { switch (status) { case ButtonStatus.HIDDEN: return 1; case ButtonStatus.ENABLED: return 2; case ButtonStatus.DISABLED: return 3; default: return 4; } } const status1 = 'HIDDEN' as ButtonStatus; // Compile success if pass valid status with String Enums console.log(TestStringEnums(status1)); const status2 = 'SHOW' as ButtonStatus; // NO Compile error if pass invalid status with String Enums console.log(TestStringEnums(status2));
- Truyền sai giá trị
status2
nhưng chương trình vẫn được transpiled và run bình thường.
-
Playground Link
Chỉ có 1 cách duy nhất để sử dụng union types, trong khi với enums bạn có thể sử dụng ButtonStatus.HIDDEN
hoặc giá trị trực tiếp 'HIDDEN'
mà không gặp phải compiler complaining.
Thêm 1 point về Typesafe cho Union types!
Union Type | String Enums |
---|---|
4 | 0 |
Iterating
- [✘] Union Type
// Union types // ? Can't iterate over a type, defining an array is needed const ButtonStatus = ['HIDDEN', 'ENABLED', 'DISABLED'] as const; // Notice that the array and type can have the same name if you want type ButtonStatus = typeof buttonStatuses[number]; for(const status of buttonStatus) { // ? the type of status here is ButtonStatus // ? always iterate in order }
- [✔] String Enums
// String enums // ? Just do it for(const status in ButtonStatus) { // ? The type of status here is string // ? iteration order not guaranteed with "in" }
Trả lại 1 point cho String Enums
Union Type | String Enums |
---|---|
4 | 1 |
Renaming
- [✘] Union Type
- Find and replace toàn Project
- [✔] String Enums
- Right click > Rename symbol
Rõ ràng String Enums tiện hơn, trả thêm 1 point cho String Enums
Union Type | String Enums |
---|---|
4 | 2 |
Tổng kết
Trong bài viết so sánh trên quan điểm cá nhân mình thì Union Type nhận được 4 điểm và String Enums nhận được 2 điểm!
Hãy sử dụng Union types by default
Nếu bạn có quan điểm khác, hãy để lại comment dưới bài viết này, xin chân thành cảm ơn các góp ý từ bạn đọc 🌺