Khi TypeScript ngày càng phổ biến, các lập trình viên đã đón nhận nó vì tính an toàn kiểu dữ liệu, khả năng mở rộng và các công cụ mạnh mẽ trong các ứng dụng web hiện đại. Cho dù bạn là người mới bắt đầu hay nhà phát triển có kinh nghiệm, việc trau dồi kỹ năng TypeScript có thể tạo ra sự khác biệt đáng kể về chất lượng, khả năng bảo trì và khả năng đọc của codebase.
Hướng dẫn này sẽ hướng dẫn bạn các mẹo thực tế và các phương pháp hay nhất để giúp bạn viết code TypeScript tốt hơn.
Tại sao bạn nên tập trung vào việc viết mã TypeScript tốt hơn?
TypeScript mang đến kiểu gõ và công cụ mạnh mẽ, nhưng cách bạn viết code rất quan trọng khi nói đến việc cung cấp giá trị, giảm lỗi và duy trì code sạch, dễ đọc. Biết cách sử dụng các tính năng của TypeScript một cách hiệu quả đảm bảo:
- Giảm lỗi: Kiểu gõ mạnh có thể giúp ngăn ngừa nhiều lỗi runtime bằng cách phát hiện các vấn đề trong thời gian biên dịch.
- Cải thiện chất lượng code: Code TypeScript sạch sẽ dễ hiểu, kiểm tra và bảo trì hơn.
- Tăng cường cộng tác: Các kiểu và interface rõ ràng giúp codebase của bạn dễ dàng hơn cho người khác tiếp cận và làm việc.
Tất tần tật các bí quyết viết mã TypeScript tốt hơn
Sau đây là những mẹo giúp bạn có thể viết được những đoạn mã tốt hơn, đảm bảo code sạch và hiệu quả.
1. Tận dụng các tùy chọn gõ nghiêm ngặt
Các tùy chọn trình biên dịch của TypeScript cho phép bạn thực thi các quy tắc kiểm tra kiểu nghiêm ngặt hơn. Việc đặt "strict": true trong tsconfig.json của bạn là một điểm khởi đầu tuyệt vời, nhưng hãy cân nhắc bật các tùy chọn bổ sung như:
- "noImplicitAny": Tránh sử dụng kiểu any ngoài ý muốn.
- "strictNullChecks": Đảm bảo các biến không thể là null hoặc undefined trừ khi được phép rõ ràng.
- "strictFunctionTypes": Thực thi suy luận kiểu hàm chính xác, ngăn ngừa các lỗi tinh vi.
Kiểu gõ nghiêm ngặt hơn thường tiết lộ các lỗi ẩn và làm cho codebase của bạn đáng tin cậy hơn.
2. Sử dụng kiểu và Interface một cách khôn ngoan
Cả type và interface đều cho phép bạn định nghĩa hình dạng của các đối tượng, nhưng mỗi loại đều có điểm mạnh riêng:
- Interface: Sử dụng interface khi định nghĩa các đối tượng, đặc biệt là khi bạn mong đợi các đối tượng có hình dạng nhất quán có thể hưởng lợi từ tính kế thừa hoặc mở rộng trong tương lai.
interface User { id: number; name: string; email: string;
}
- Type: Sử dụng type cho các union hoặc tạo các cấu trúc dữ liệu phức tạp hơn mà bạn không cần mở rộng.
type Status = "active" | "inactive" | "pending";
Hiểu khi nào nên sử dụng từng loại sẽ dẫn đến code dễ bảo trì và dự đoán hơn.
3. Ưu tiên unknown hơn any
Kiểu any thường bị sử dụng sai, vì nó cho phép bất kỳ loại dữ liệu nào, làm mất tác dụng của tính an toàn kiểu của TypeScript. Thay vào đó, hãy chọn unknown khi kiểu không chắc chắn. Không giống như any, unknown yêu cầu kiểm tra kiểu trước khi bạn có thể thực hiện các thao tác trên đó, tăng cường tính an toàn.
function processInput(input: unknown) { if (typeof input === "string") { console.log(input.toUpperCase()); }
}
4. Sử dụng Readonly và kiểu bất biến để an toàn
Thêm readonly vào các thuộc tính có thể ngăn chặn sự thay đổi ngẫu nhiên, điều này rất có giá trị trong nhiều trường hợp, đặc biệt là khi xử lý các cấu trúc dữ liệu không nên thay đổi sau khi được khởi tạo.
interface Product { readonly id: number; readonly name: string; price: number;
}
Sử dụng readonly cho các thuộc tính không nên bị thay đổi làm giảm lỗi và làm rõ tính bất biến của một số dữ liệu nhất định trong code của bạn.
5. Định nghĩa kiểu tiện ích để tái sử dụng
TypeScript cung cấp một số kiểu tiện ích (Partial, Pick, Omit, Readonly, v.v.) giúp code của bạn ngắn gọn hơn và giúp tránh các định nghĩa lặp lại. Ví dụ: nếu bạn muốn một phiên bản của User với tất cả các thuộc tính tùy chọn, hãy sử dụng Partial<User>.
type OptionalUser = Partial<User>;
Các kiểu tiện ích này giúp đơn giản hóa việc xử lý các biến thể trong kiểu, làm cho code của bạn linh hoạt hơn.
6. Định nghĩa rõ ràng kiểu trả về
Khi định nghĩa các hàm, hãy luôn chỉ định kiểu trả về. Điều này không chỉ làm cho code dễ dự đoán hơn mà còn giúp TypeScript phát hiện lỗi nếu hành vi của hàm thay đổi sau này.
function getUser(id: number): User | null { // logic to fetch user
}
Các kiểu trả về rõ ràng làm giảm sự mơ hồ và giúp đảm bảo hàm hoạt động như mong đợi.
7. Xử lý Null và Undefined một cách an toàn
Các kiểu như null và undefined thường gây ra lỗi runtime nếu không được xử lý đúng cách. TypeScript cung cấp các toán tử optional chaining (?.) và nullish coalescing (??) để xử lý các trường hợp này một cách duyên dáng.
const userName = user?.profile?.name ?? "Guest";
Các toán tử này giúp bạn tránh các lỗi phổ biến xung quanh giá trị null mà không cần các kiểm tra phức tạp, lồng nhau.
8. Sử dụng Enum cho các giá trị có ý nghĩa
Enum trong TypeScript cho phép bạn định nghĩa một tập hợp các hằng số được đặt tên. Chúng làm cho code của bạn diễn đạt hơn và ngăn việc sử dụng các chuỗi hoặc số tùy ý.
enum UserRole { Admin = "ADMIN", User = "USER", Guest = "GUEST",
} function assignRole(role: UserRole) { // logic here
}
Enum đặc biệt hữu ích khi xử lý một tập hợp các tùy chọn cố định, làm cho code tự ghi lại và giảm lỗi.
9. Sử dụng never cho kiểm tra toàn diện
Khi làm việc với các kiểu union, hãy sử dụng never để đảm bảo kiểm tra toàn diện trong các trường hợp switch. Điều này đảm bảo rằng nếu các trường hợp mới được thêm vào union, TypeScript sẽ báo lỗi nếu chúng không được xử lý.
type Shape = Circle | Square | Triangle; function getArea(shape: Shape) { switch (shape.type) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side * shape.side; default: const _exhaustiveCheck: never = shape; return _exhaustiveCheck; }
}
Kỹ thuật kiểm tra kiểu never này làm giảm nguy cơ các trường hợp không được xử lý, đảm bảo code của bạn toàn diện và an toàn về kiểu.
10. Giữ cho các chức năng thuần túy và súc tích
Viết các hàm thuần khiết - các hàm không có tác dụng phụ - giúp ngăn chặn hành vi không thể đoán trước và làm cho việc kiểm tra đơn giản hơn. TypeScript tỏa sáng khi được sử dụng trong lập trình hàm vì nó thực thi tính thuần khiết trong thiết kế hàm, khuyến khích bạn giữ cho các hàm ngắn gọn và có thể dự đoán được.
function add(a: number, b: number): number { return a + b;
}
Các hàm thuần khiết dễ kiểm tra, gỡ lỗi và hiểu hơn, làm cho code TypeScript của bạn mạnh mẽ hơn.
Kết luận
Viết code TypeScript tốt hơn có nghĩa là tập trung vào kiểu gõ, tính nhất quán của code và các phương pháp hay nhất giúp codebase của bạn có khả năng phục hồi, bảo trì và mở rộng tốt hơn. Khi bạn áp dụng những mẹo này, bạn sẽ thấy rằng code TypeScript của bạn trở nên sạch hơn, ít lỗi hơn và dễ làm việc hơn.