Vì sao TypeScript là mặc định của web dev 2026? Lộ trình chuyển từ JS sang TS

5 giờ tới · 10 phút đọc
Tại sao TypeScript thắng?
Mình nhớ hồi 2020, mình gõ npm install --save-dev typescript xong ngồi nhìn file tsconfig.json không biết bắt đầu từ đâu. Đồng nghiệp bảo "TypeScript chỉ làm khó thêm thôi". Mình tin theo và bỏ qua luôn.
Rồi 6 tháng sau, mình nhận bug report: production crash vì undefined is not a function. Cái bug mà TypeScript đã bắt được ngay lúc viết code.
Hiện tại, 95% of top 100 npm packages had TypeScript support in 2024, with 68% of JS developers using TypeScript according to State of JS 2025 survey (State of JS 2025 Survey and npm Package-Pulse Dataset) dự án lớn trên GitHub đã dùng TypeScript. Đây không phải trend - đây là sự thay đổi cơ bản trong cách viết JS.
JS không báo lỗi cho đến khi user gặp bug - TS bắt lỗi ngay lúc viết code
Lý do TS thắng không phải vì nó "fancy" hơn. Lý do thực tế hơn nhiều:
Autocomplete chính xác. IDE biết chính xác một object có property gì, function nhận kiểu dữ liệu gì. Không cần mở docs mỗi 5 phút.
Refactor không sợ. Đổi tên một function? TS sẽ báo tất cả chỗ cần update. JS thì chúc may mắn với Ctrl+F.
Tự document hóa code. Type annotations là documentation sống - không bao giờ outdated vì nếu outdated thì code không compile được.
Với các dự án lớn có nhiều người, những lợi ích này nhân lên theo số lượng developer. Đó là lý do tại sao hầu hết công ty tech lớn đã chuyển sang TS từ vài năm trước.
Setup TypeScript đúng cách từ đầu
Cài TS thì dễ. Cấu hình đúng mới là vấn đề. Mình thấy nhiều người copy paste tsconfig.json từ StackOverflow mà không hiểu từng option nghĩa là gì.
Đừng bỏ qua tsconfig - đây là nơi quyết định TS strict đến đâu
File tsconfig.json quan trọng nhất với các option sau:
Option strict: true bật 8 flag khác nhau cùng lúc, trong đó quan trọng nhất là strictNullChecks. Với option này, bạn không thể gán null hay undefined cho biến không khai báo kiểu nullable - chính xác là những bug phổ biến nhất trong JS.
Nếu bạn đang học JavaScript và muốn có nền tảng vững trước khi học TS, khóa Lập Trình JavaScript Nâng Cao trên F8 cover closure, prototype và cách JS thực sự hoạt động - những thứ sẽ giúp bạn hiểu TS sâu hơn nhiều.
Type annotations cơ bản và những thứ hay bị nhầm
Phần này mình sẽ đi thẳng vào những pattern thực tế - không phải lý thuyết string, number, boolean mà docs nào cũng có.
Union types - hay dùng hơn bạn nghĩ:
Interface vs Type - khi nào dùng cái nào:
Interface cho phép extend sau khi khai báo, Type alias thì không - chọn đúng từ đầu tiết kiệm refactor
Generics - đừng sợ cái dấu <T>:
Type narrowing - tính năng ít được nhắc đến nhưng cực kỳ hữu ích:
Discriminated union là pattern cực kỳ mạnh khi làm việc với API responses có nhiều dạng khác nhau.
Schema validation với Zod và Valibot
Type annotations chỉ hoạt động lúc compile time. Vấn đề là dữ liệu từ API, form input hay localStorage không có ai kiểm tra kiểu lúc runtime.
Đây là chỗ Zod và Valibot vào.
TypeScript bảo vệ lúc viết code, Zod/Valibot bảo vệ lúc chạy - cần cả hai
Zod - battle-tested, ecosystem lớn:
Valibot - nhẹ hơn Zod nhỏ hơn đáng kể so với Zod:
Chọn Zod nếu dự án đã có ecosystem liên quan (tRPC, React Hook Form, Drizzle). Chọn Valibot nếu bundle size là ưu tiên - đặc biệt quan trọng với mobile web.
Migration guide: từng bước chuyển JS sang TS mà không break
Đây là phần quan trọng nhất. Mình đã migrate vài dự án JS sang TS và có 2 cách tiếp cận:
Cách 1 - Big bang (không khuyến khích): Đổi tất cả file .js sang .ts một lần. Kết quả: 500 lỗi compile, team panic, revert về JS.
Cách 2 - Incremental (đúng cách): Chạy song song JS và TS, migrate từng file.
Migration từng bước giúp dự án luôn chạy được trong quá trình chuyển đổi
Bước 1: Setup allowJs để JS và TS cùng tồn tại
Bước 2: Đổi file từ dễ đến khó
Thứ tự migrate hợp lý:
- Utility functions - thuần logic, ít dependency
- Type definitions - tạo
types/folder, định nghĩa interfaces - API layer - đây là nơi có nhiều bug nhất do dữ liệu không đoán trước được
- Components/Controllers - cuối cùng, sau khi đã có types
Bước 3: Handle third-party libraries
Nếu thư viện không có types:
Bước 4: Bật strict dần dần
Cách này giúp team không bị overwhelmed với 500 lỗi cùng một lúc. Mỗi tuần fix một loại lỗi, dần dần codebase sẽ sạch hẳn.
Best practices: any, unknown, và cách viết type-safe code
Phần này mình chia sẻ những gì mình học được sau vài năm viết TS - không phải lý thuyết, là kinh nghiệm thực tế.
any vs unknown - khác nhau hoàn toàn
Khi nào dùng any hợp lý:
- Trong quá trình migration (tạm thời, có TODO comment)
- Khi viết type cho thư viện quá phức tạp không xứng đáng mất thời gian
- Test files (đôi khi)
Không bao giờ dùng any:
- API response (dùng Zod hoặc khai báo type cụ thể)
- Event handlers
- Shared utility functions
unknown yêu cầu bạn kiểm tra type trước khi dùng - đây là điểm khác biệt quan trọng với any
Một số pattern type-safe hay dùng
Checklist trước khi merge
Mình có thói quen check 3 thứ này trước khi push code TS:
- Không có
anymới (ngoại lệ phải có comment giải thích) - Mọi async function đều có return type rõ ràng
- Mọi API boundary đều có Zod/Valibot validation
Nếu bạn đang build dự án React với TS, khóa Xây Dựng Website với ReactJS trên F8 có cover cách dùng React + TypeScript trong môi trường thực tế.
