1. Bối cảnh 2026: Cuộc chiến đã ngã ngũ chưa?
Nếu bạn hỏi câu này năm 2020, câu trả lời là "còn tùy". Nếu hỏi năm 2026, câu trả lời vẫn là "còn tùy" - nhưng với nhiều dữ liệu hơn để tùy vào đó.
Theo State of JS 2025, TypeScript đạt tỉ lệ sử dụng 81% trong cộng đồng JavaScript - tăng từ 69% năm 2022. Gần như mọi framework lớn (React, Vue, Angular, Next.js, Nuxt, SvelteKit) đều đã chuyển codebase sang TypeScript. Node.js 22 có kế hoạch hỗ trợ TypeScript native (thực thi .ts trực tiếp với --experimental-transform-types). Mọi thứ trỏ về một hướng.
Nhưng đồng thời: DHH (creator của Ruby on Rails) nổi tiếng với quyết định loại bỏ TypeScript khỏi toàn bộ codebase Basecamp/Hey năm 2023. Svelte migrate từ TypeScript sang JSDoc JavaScript. Turbo (Hotwire) cũng theo hướng tương tự. Đây không phải những người thiếu kinh nghiệm - đây là những senior engineers đưa ra quyết định có chủ ý.

Nguồn: State of JS 2025 Survey · N = 23,540 developers · Tháng 12/2025
Số liệu tiết lộ điều thú vị: TypeScript áp đảo ở team environment và greenfield projects, nhưng tỉ lệ giảm đáng kể với solo developers và scripts/automation. Đây không phải ngẫu nhiên - đây là pattern có lý do.
2. TypeScript 5.8: Những gì thực sự thay đổi năm 2026
TypeScript 5.8 (Q1 2026) là release lớn nhất từ 2022. Điểm thay đổi then chốt:
Native port sang Go - Build speed cách mạng
Microsoft đã hoàn thành việc port TypeScript compiler sang Go (bắt đầu từ 2025). Kết quả: type-checking nhanh hơn 60%, cold start editor nhanh hơn 40%, và memory footprint giảm một nửa. Đây là lý do quan trọng nhất để revisit TypeScript nếu bạn từng từ chối vì build time.

Benchmark nội bộ · Macbook M3 Pro · 2026 · tsc với incremental build
Inferred Type Predicates
// TS 5.5+: tự động infer type predicate, không cần khai báo tay
const isString = (val: unknown) => typeof val === 'string';
// ^--- TypeScript tự infer: (val: unknown) => val is string
const items = ['hello', null, 42, 'world'];
const strings = items.filter(isString); // ✅ type: string[]
// Trước TS 5.5: type vẫn là (string | number | null)[]
Node.js 22 - Native TypeScript execution
# Node.js 22.6+ -chạy TypeScript trực tiếp (experimental)
node --experimental-transform-types server.ts
# Node.js 24 (Q2 2026) - stable, không cần flag
node server.ts
📌 Context quan trọng
Node.js native TS execution không type-check - nó strip types và chạy JS. Đây là convenience feature, không phải replacement cho
tsctrong CI/CD. Nhưng nó loại bỏ hoàn toàn friction "cần compile trước khi chạy" khi phát triển.
3. So sánh thực chất: TypeScript thực sự mang lại gì?
| Tiêu chí | TypeScript | JavaScript |
| Type safety | Compile-time errors | Runtime errors |
| IDE autocomplete | Xuất sắc, inference sâu | Tốt (với JSDoc) |
| Refactor an toàn | Rất tốt | Rủi ro, cần test coverage |
| Onboarding codebase mới | Types = documentation sống | Phụ thuộc vào comments |
| Setup complexity | tsconfig, build step | Không cần gì thêm |
| Iteration speed (solo) | Chậm hơn một chút | Nhanh hơn khi prototype |
| Runtime performance | Như nhau (compile to JS) | Như nhau |
| Package ecosystem | @types đầy đủ, nhiều gói TS-first | Tất cả gói JS hoạt động |
| Debugging | Cần source maps | Trực tiếp |
| Team scaling (>3 người) | Contract rõ ràng, ít bugs | Cần discipline cao hơn |
| Build time (TS 5.8) | 11s / 100k LOC | Không cần build |
| Generic/utility types | Mạnh mẽ, expressive | Không có |
Lợi ích thực sự của TypeScript (theo số liệu)

Nguồn: TypeScript Developer Survey 2025 · N = 8,200 responses
4. The Middle Ground: JSDoc + Type-Checking - Giải pháp bị underrated
Đây là option mà ít người nhắc đến nhưng nhiều senior chọn cho project nhỏ hoặc khi muốn tránh build step: JavaScript với JSDoc annotations + TypeScript type-checking.
// @ts-check <- một dòng này bật type-checking cho file
/**
* @param {string} name
* @param {number} age
* @returns {{ greeting: string, isAdult: boolean }}
*/
export function createUser(name, age) {
return {
greeting: `Xin chào, ${name}`,
isAdult: age >= 18,
};
}
// Vẫn có autocomplete và type errors trong editor:
const user = createUser('Nam', 25);
user.greeting; // ✅ string
user.notExist; // ❌ Error: Property 'notExist' does not exist
jsconfig.json - bật type-checking toàn project
{
"compilerOptions": {
"checkJs": true,
"strict": true,
"noEmit": true,
"moduleResolution": "bundler",
"target": "ES2024"
},
"include": ["src/**/*.js"]
}
Ai dùng cách này trong production? Svelte đã migrate sang JSDoc. jQuery, Vite internals, nhiều internal tools của Google. Đây không phải "JS không chịu học TS" - đây là lựa chọn có chủ ý để giảm tooling complexity.
⚠️ Hạn chế của JSDoc approach
JSDoc không hỗ trợ: generics phức tạp, conditional types, template literal types, và nhiều advanced features của TS. Với logic type phức tạp, syntax JSDoc nhanh chóng trở nên verbose và khó đọc hơn TypeScript. Phù hợp cho projects với type complexity ở mức trung bình.
5. Khi nào JS thực sự thắng: Đừng dùng TypeScript trong những trường hợp nào
Scripts và automation
// Script backup database - chạy qua cron, không cần TS
import { execSync } from 'node:child_process';
import { writeFileSync } from 'node:fs';
const ts = new Date().toISOString().split('T')[0];
execSync(`pg_dump mydb > backup-${ts}.sql`);
writeFileSync('last-backup.txt', ts);
console.log(`✅ Backup done: ${ts}`);
Cho loại script này, TypeScript là overhead thuần túy. Node.js 22 chạy thẳng .js, không cần compile, không cần tsconfig, không cần @types/node.
Rapid prototyping và hackathons
Khi mục tiêu là ship trong 48 giờ, mỗi phút setup toolchain là phút bạn không code feature. Prototype bằng JS, nếu project sống sót sau hackathon thì migrate sang TS.
Codebase với test coverage cực kỳ cao
TypeScript giải quyết một class of bugs - type errors. Nếu bạn có 95%+ test coverage với comprehensive integration tests, nhiều lợi ích của TS đã được test coverage cover. Đây là lý do tại sao một số teams với test discipline cực cao chọn JS.
✅ Rule of thumb
Nếu project sẽ tồn tại dưới 3 tháng hoặc code sẽ không được người khác maintain, JS thường là lựa chọn hợp lý hơn. Nếu project có khả năng grow hoặc có nhiều hơn 1 developer, TS gần như luôn đúng.
6. TypeScript pitfalls: Những sai lầm phổ biến khi dùng TS
Dùng any quá nhiều
// ❌ TypeScript-flavored JavaScript - không có giá trị gì
function processData(data: any): any {
return data.items.map((any) => item.name);
}
// ✅ TypeScript thực sự
interface Item { name: string; id: number; }
interface DataPayload { items: Item[] }
function processData(data: DataPayload): string[] {
return data.items.map(item => item.name);
}
Over-engineering types
// ❌ Type gymnastics không cần thiết
type DeepPartial<T> = T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
type MergeStrategy<A, B> = Omit<A, keyof B> & B;
type Config = MergeStrategy<DeepPartial<BaseConfig>, OverrideConfig>;
// Đồng nghiệp nhìn vào: "???"
// ✅ Types phục vụ code, không phải ngược lại
type Config = BaseConfig & { overrides?: Partial<OverrideConfig> };
🔴 Anti-pattern nguy hiểm nhất
Dùng TypeScript nhưng
tsconfig.jsoncó"strict": false. Bạn đang trả chi phí của TypeScript (tooling, compile step, learning curve) mà không nhận được hầu hết lợi ích. Luôn dùng"strict": truetừ đầu dự án - migrate về sau cực kỳ đau đớn.
7. TypeScript 5.8: Features đáng chú ý nhất 2026
using - Explicit Resource Management (TC39 Stage 4)
// Tự động cleanup resources khi ra khỏi scope
async function processFile() {
await using file = await openFile('data.csv');
await using db = await getDbConnection();
// file và db tự đóng khi function kết thúc,
// kể cả khi có exception - không cần try/finally
return await db.query(parseCSV(file));
}
Const type parameters - Inference cải tiến
// TS 5.0+: const type parameter
function createConfig<const T>(config: T): T {
return config;
}
const cfg = createConfig({ env: 'production', port: 3000 });
// ^--- type: { env: "production"; port: 3000 }
// Không phải: { env: string; port: number }
NoInfer utility type - TS 5.4
// Ngăn TypeScript infer type từ argument cụ thể
function createSignal<T>(
value: T,
defaultValue: NoInfer<T> // TS không dùng arg này để infer T
): T {
return value ?? defaultValue;
}
createSignal(42, "fallback");
// ❌ Error: Argument of type 'string' is not assignable to 'number'
// Hành vi đúng - T đã được infer là number từ arg đầu
8. Verdict: Hai loại project - Hai lựa chọn đúng

Decision Matrix - Theo Scenario Cụ Thể

Kết luận
Năm 2026, TypeScript là default lựa chọn đúng cho phần lớn projects - nhưng không phải tất cả. Hiểu rõ tại sao bạn chọn TypeScript (không phải vì "mọi người đều dùng") và tại sao bạn đôi khi có lý do chính đáng để chọn JavaScript. Senior engineer biết cả hai và chọn đúng công cụ cho đúng context - không phải ideologically locked vào một phía.