TypeScript

Câu hỏi phỏng vấn TypeScript

73+ câu hỏi TypeScript phổ biến cho dev frontend/fullstack — bao gồm TS 7.0 RC.

A. Cơ bản

1. TypeScript là gì? Tại sao dùng?

TypeScript = JavaScript + static type system. Compile sang JS. Lợi ích: bắt bug sớm, IDE autocomplete/refactor mạnh, self-documenting, scale tốt với codebase lớn. Type không tồn tại runtime.

2. TS khác JS ở đâu?

TS thêm: kiểu, generic, enum, interface, decorator. JS chạy thẳng trên trình duyệt/Node. TS phải compile (qua tsc, tsx, swc, esbuild, hoặc Node 23+ với --strip-types).

3. TS 7.0 có gì mới?

TS 7.0 là bản nâng cấp lớn nhất trong lịch sử TypeScript với compiler Go rewrite (tsgo).

  • tsgo — compiler viết bằng Go, compile nhanh 10x, editor startup nhanh ~8x.
  • --checkers--builders flag — parallelism cho type-check và emit.
  • strict: true trở thành default từ TS 6.0, được giữ nguyên trong 7.0.
  • module: esnext trở thành default (trước đây là commonjs).
  • types: [] mặc định — không tự động scan @types/*, phải khai báo rõ.
  • noUncheckedSideEffectImports: true mặc định — cấm import có side-effect không kiểm soát.
  • stableTypeOrdering bắt buộc — deterministic type ordering cho parallelism.
  • Remove target: es5 — minimum target là es2020.
  • Remove module: amd | umd | systemjs — chỉ giữ esnext, commonjs, node16, nodenext.
  • Remove moduleResolution: node | classic — chỉ còn bundler, node16, nodenext.
  • Remove baseUrl, remove preserveConstEnums.
  • Unicode template literal fix — sửa bug surrogate pairs và combining characters.
  • Reduced context sensitivity — giảm ambiguous parse edge case.

4. TS 7 (Corsa / tsgo) là gì?

Corsa là codename cho dự án viết lại TypeScript compiler bằng Go. Tên chính thức của compiler binary là tsgo.

  • RC1 ra mắt tháng 6/2026, stable dự kiến Q3/2026.
  • Compile nhanh 5-10x, editor startup nhanh ~8x so với tsc TypeScript cũ.
  • Viết bằng Go để tận dụng multi-threading native, memory efficiency và compile-to-native speed.
  • LSP server cũng được viết lại, phản hồi gần như tức thì kể cả với codebase >100k LOC.
  • TS 6.0 là bản transition — giữ tsc cũ nhưng thêm deprecation warning và default mới để chuẩn bị cho TS 7.0.

5. strict mode bao gồm flag nào?

noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, alwaysStrict, useUnknownInCatchVariables, noImplicitThis. Project mới luôn bật. Từ TS 6.0+, strict: true là default cho project mới.

6. tsc --noEmit để làm gì?

Chỉ type-check, không emit JS. Dùng ở CI / pre-commit để check type mà không build. Build thật do bundler (Vite, esbuild) làm. Với TS 7.0, dùng tsgo --noEmit — nhanh hơn 10x.

B. Type cơ bản

7. any vs unknown vs never?

  • any: tắt type check — escape hatch, dùng càng ít càng tốt.
  • unknown: any an toàn — phải narrow trước khi dùng.
  • never: không có giá trị — function throw / loop vô tận trả never. Dùng cho exhaustive check.

8. null vs undefined?

undefined = chưa gán, null = gán có chủ ý = không gì. Với strictNullChecks, 2 type khác nhau, phải khai báo rõ.

9. Type assertion as có check gì không?

Không. as chỉ tell compiler tin bạn, không validate runtime. Sai → bug.

10. ! (non-null assertion) là gì?

Tell compiler "tôi chắc giá trị không null/undefined". el!.click(). Cẩn thận — sai sẽ crash runtime.

11. as const dùng làm gì?

Ép literal narrow, immutable. Object/array thành readonly + literal type:

const colors = ["red", "blue"] as const;  // readonly ["red", "blue"]

12. satisfies (TS 4.9+) khác as ra sao?

as không check — bypass. satisfies check value khớp type nhưng giữ literal narrow:

const palette = { red: [255,0,0] } satisfies Record<string, [number,number,number]>;
palette.red[0]      // number — không bị widen từ tuple thành number[]

C. Union, intersection, narrowing

13. Union | vs Intersection &?

  • A | B: value là A HOẶC B (OR).
  • A & B: value có đủ field A VÀ B (AND).

14. Discriminated union là gì?

Mỗi union member có 1 field "discriminator" giá trị literal:

type Shape = { kind: "circle"; r: number } | { kind: "square"; s: number };

switch trên kind → TS auto-narrow type, autocomplete đúng.

15. Type narrowing có những cách nào?

  • typeof (primitive)
  • instanceof (class)
  • in operator (key tồn tại)
  • Truthiness (if (x))
  • Equality (===, !==)
  • Discriminated union (switch on tag)
  • Custom type guard (x is Type)
  • Assertion function (asserts x is Type)

16. Type guard (x is Type) là gì?

Function trả param is Type → khi true, TS narrow param sang Type:

function isString(x: unknown): x is string {
  return typeof x === "string";
}

17. Exhaustive check với never?

Pattern bắt compile-time khi quên handle case mới:

default:
  const _: never = s;
  throw new Error(`Unhandled: ${s}`);

D. type vs interface

18. type vs interface — khi nào dùng cái nào?

Cả 2 mô tả object shape. Interface: extends, declaration merging — chuyên cho object/class. Type: flexible — làm được union, intersection, tuple, mapped. Rule: object public API → interface, alias/union/utility → type.

19. Declaration merging?

Cùng tên interface 2 lần → merge thành 1. Dùng để augment lib ngoài (mở rộng Express.Request...).

20. extends vs &?

  • interface B extends A: B kế thừa A (1 quan hệ).
  • type B = A & X: intersection — gộp.

Khác biệt nhỏ: extends nhanh hơn check, intersection tạo type mới.

E. Generic

21. Generic giải quyết gì?

Code reuse + type-safety. Function/class chạy với nhiều type mà vẫn giữ type info — không cần any rồi cast.

22. Constraint T extends U là gì?

Hạn chế T phải compatible với U:

function len<T extends { length: number }>(x: T) { return x.length; }

23. keyof T trả về gì?

Union các key của T dưới dạng string literal type:

keyof { id: number; name: string }   // "id" | "name"

24. T[K] (lookup) là gì?

Lấy value type theo key:

type Name = User["name"];          // string

25. Generic default?

<T = string> — nếu không truyền T, dùng default.

26. Generic constraint với keyof — pattern get?

function get<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

Đảm bảo key là một trong các key của obj, return đúng type.

F. Conditional, mapped, infer

27. Conditional type T extends U ? X : Y?

Type chọn theo điều kiện. T extends U check assignability.

28. Distributive conditional?

Khi T là naked type parameter (T extends X) và T là union → conditional apply cho từng union member rồi gộp:

type ToArray<T> = T extends any ? T[] : never;
type R = ToArray<string | number>;   // string[] | number[]

29. Cách chống distribute?

Wrap T trong tuple: [T] extends [U] ? .... Không còn naked → không distribute.

30. infer keyword?

Đặt biến type trong nhánh conditional → extract type:

type Return<F> = F extends (...args: any) => infer R ? R : never;

31. Mapped type là gì?

Tạo type mới bằng cách map qua keys của type khác:

type Readonly<T> = { readonly [K in keyof T]: T[K] };

32. Key remapping (TS 4.1+)?

[K in keyof T as NewKey] — đổi tên key:

type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

33. Template literal type?

Type là string literal có placeholder: `Hello, ${string}!`. Combine union để sinh permutation, dùng với infer để parse string ở type level.

G. Utility types

34. Pick<T, K> định nghĩa thế nào?

type Pick<T, K extends keyof T> = { [P in K]: T[P] };

35. Omit<T, K> định nghĩa?

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

36. Partial<T> định nghĩa?

type Partial<T> = { [P in keyof T]?: T[P] };

37. Required<T>?

type Required<T> = { [P in keyof T]-?: T[P] };

(-? = remove optional modifier.)

38. Readonly<T>?

type Readonly<T> = { readonly [P in keyof T]: T[P] };

39. Record<K, V>?

type Record<K extends keyof any, V> = { [P in K]: V };

40. ReturnType<F>?

type ReturnType<F extends (...a: any) => any> = F extends (...a: any) => infer R ? R : never;

41. Awaited<T>?

Unbox Promise đệ quy: Awaited<Promise<Promise<string>>> = string.

42. Exclude<T, U> vs Extract<T, U>?

  • Exclude<T, U>: T loại U.
  • Extract<T, U>: T giao U.
Exclude<"a"|"b"|"c", "a">   // "b"|"c"
Extract<"a"|"b"|"c", "a"|"d"> // "a"

H. Function & class

43. Method overload trong TS?

function len(x: string): number;
function len(x: any[]): number;
function len(x: any): number { return x.length; }

Khai báo nhiều signature, implementation 1 cái.

44. this parameter?

function greet(this: { name: string }) { return this.name; }

TS check call site phải có this đúng type. Không emit code.

45. Class field arrow vs method?

  • method()this dynamic, bị mất khi unbind.
  • arrowField = () => {}this lexical, luôn = instance. Tốt cho React handler.

46. private TS vs #private JS?

  • private TS: compile-time only, runtime vẫn truy cập được.
  • #private JS native: runtime enforced, truly private.

Mới project → ưu tiên #.

47. abstract class trong TS?

Class không instantiate trực tiếp, ép subclass implement abstract method:

abstract class Animal {
  abstract speak(): string;
}

I. Decorator & enum

48. Decorator có 2 dạng — khác nhau ra sao?

  • Legacy (experimentalDecorators + emitDecoratorMetadata): NestJS, Angular cũ, TypeORM.
  • TC39 stage 3 (stable TS 5.0+, metadata 5.9): chuẩn ECMAScript, signature khác.

Đang migrate dần — hiểu cả 2.

49. Vì sao Enum đang bị deprecate?

Enum emit code runtime → khó tree-shake → bundle phình. Khuyến nghị const + as const:

const Status = { Active: "active", Inactive: "inactive" } as const;
type Status = typeof Status[keyof typeof Status];

50. const enum khác enum?

const enum inline literal vào nơi dùng — không emit code runtime. Trade-off: không debug runtime được, không hoạt động với isolatedModules. ⚠️ TS 7.0 đã remove preserveConstEnums — const enum luôn inline, không emit object runtime.

J. Real-world

51. Type-safe HTTP API client?

Dùng generic + Zod/Valibot để validate runtime:

async function fetchJson<T>(url: string, schema: ZodType<T>): Promise<T> {
  const data = await fetch(url).then(r => r.json());
  return schema.parse(data);
}

52. Branded type cho ID?

type UserId = number & { __brand: "UserId" };

Chống nhầm UserId với OrderId dù cùng number.

53. Type-safe Object.keys?

function typedKeys<T extends object>(o: T): (keyof T)[] {
  return Object.keys(o) as (keyof T)[];
}

Object.keys trả string[] — phải cast về (keyof T)[].

54. Module augmentation?

Mở rộng type của module ngoài:

declare module "express" {
  interface Request { user?: User; }
}

55. .d.ts file là gì?

Declaration file — chỉ chứa type, không có implementation. Dùng để type lib không có type (@types/...) hoặc xuất type cho lib bạn publish.

K. Performance & tooling

56. tsc chậm — giải pháp?

TS 7.0 (tsgo) chính là giải pháp: compile nhanh 10x, editor startup ~8x nhanh hơn. Nếu chưa migrate được:

Trước TS 7.0 (vẫn dùng tsc cũ):

  • incremental: true + tsBuildInfoFile.
  • Project references chia monorepo.
  • skipLibCheck: true.
  • Dùng swc / esbuild cho build (chỉ strip type, không check).
  • CI: tsc --noEmit chạy parallel với build.

TS 7.0 (tsgo):

  • --checkers N — số worker song song cho type-checking, mặc định = số CPU core.
  • --builders N — số worker song song cho emit JS/output.
  • Worker pool xử lý các file độc lập cùng lúc, thay vì tuần tự như tsc cũ.
  • Ví dụ: tsgo --checkers 8 --builders 4 --noEmit

57. ESM vs CommonJS — chọn gì?

ESM là default từ TS 7.0module: esnext mặc định cho project mới.

  • CommonJS đã là legacy. Không hỗ trợ tree-shake, dynamic import khác cú pháp.
  • ESM modern, tree-shake tốt, async import native.
  • ⚠️ TS 7.0 đã remove module: amd | umd | systemjs — chỉ còn esnext, commonjs, node16, nodenext.
  • Bẫy ESM: import phải kèm .js extension dù file là .ts:
    import { foo } from "./foo.js";  // đúng, dù file là foo.ts
    

58. isolatedModules: true để làm gì?

Ép mỗi file compile độc lập — bắt buộc với esbuild/swc. Cấm một số TS feature (const enum, namespace re-export).

59. Babel TypeScript vs tsc?

Babel chỉ strip type, không check. Nhanh hơn nhưng không bắt lỗi type. → Dev nhanh dùng Babel/swc/esbuild, CI dùng tsc --noEmit check. Với TS 7.0, tsgo --noEmit nhanh hơn 10x nên có thể dùng trực tiếp trong dev loop.

60. Bạn dùng TS bao lâu? Project lớn nhất?

Câu open-ended — kể project thực, các challenge gặp (generic deep, conditional type cho API client, migration JS→TS, performance build). Bonus: nếu đã trải qua migration TS 5.x → 6.0 → 7.0, kể về quá trình update tsconfig, fix deprecation, và hiệu năng sau khi chuyển sang tsgo.

L. TypeScript 7.0 — Migration & Breaking Changes

61. TS 7.0 có gì khác TS 6.0 về mặt kiến trúc?

TS 7.0 là cuộc đại tu kiến trúc lớn nhất trong lịch sử TypeScript.

TS 6.x trở về trướcTS 7.0 (tsgo)
Ngôn ngữ compilerTypeScript / JavaScriptGo
RuntimeNode.jsNative binary
ParallelismSingle-threadMulti-thread (worker pool)
PipelineParse → Bind → Check → Emit tuần tựParse song song, check song song, emit song song
MemoryV8 GC overheadGo memory model, thấp hơn đáng kể
LSPTypeScript-based, khởi động chậmViết lại native, phản hồi gần như tức thì

Về mặt type system, TS 7.0 tương thích ngược với TS 6.x — không có breaking change lớn về type-level. Thay đổi tập trung vào compiler infrastructure và performance.

62. --checkers--builders flag hoạt động ra sao?

Hai flag kiểm soát parallelism trong tsgo — tính năng cốt lõi giúp đạt tốc độ 10x:

  • --checkers N — số worker chạy song song cho type-checking. Mỗi checker nhận một nhóm file và type-check độc lập. Mặc định = os.cpus().length.
  • --builders N — số worker chạy song song cho emit JS / declaration. Mặc định = số CPU core.
# Type-check với 8 worker, không emit
tsgo --checkers 8 --noEmit

# Build với 4 checker + 4 builder
tsgo --checkers 4 --builders 4

# Tận dụng tối đa CPU (mặc định)
tsgo

Cơ chế: tsgo chia file thành các chunk, phân phối cho worker pool. stableTypeOrdering đảm bảo kết quả type-checking nhất quán bất kể worker nào hoàn thành trước. Khác hoàn toàn với tsc cũ — toàn bộ pipeline là single-thread, tuần tự.

63. Những default nào thay đổi trong TS 6.0 / 7.0?

Quá trình thay đổi default diễn ra qua 2 phiên bản để giảm shock cho hệ sinh thái:

OptionTS 5.xTS 6.0TS 7.0
strictfalse (default)true (cho project mới)true
modulecommonjscommonjs (cảnh báo)esnext
typesauto-scan @types/*auto-scan (deprecation warning)[] (không auto-scan)
noUncheckedSideEffectImportsfalsefalse (cảnh báo)true

Ý nghĩa thực tế:

  • Project mới tạo bằng TS 7.0 sẽ ESM-first, strict by default, không auto-scan global types.
  • Code cũ cần update tsconfig rõ ràng khi migrate.

64. Những option nào bị remove trong TS 7.0?

TS 7.0 xóa các option legacy để giảm maintenance burden và tập trung vào modern JavaScript:

Option bị removeLý doThay thế
target: es5ES5 quá cũ, không còn phù hợptarget: es2020 trở lên
module: amdAMD không còn được dùngmodule: esnext
module: umdUMD legacy, bundler hiện đại không cầnmodule: esnext
module: systemjsSystemJS gần như tuyệt chủngmodule: esnext
moduleResolution: nodeResolution cũ, không chuẩn ESMmoduleResolution: bundler hoặc node16
moduleResolution: classicQuá cũ, không ai dùngmoduleResolution: bundler
baseUrlGây nhập nhằng với ESM pathpaths với relative mapping
preserveConstEnumsConst enum luôn inline trong TS 7.0Không cần — mặc định behavior mới
// tsconfig.json cho TS 7.0
{
  "compilerOptions": {
    // Không còn target: "es5"
    "target": "es2022",
    // Không còn module: "amd" | "umd" | "systemjs"
    "module": "esnext",
    // Không còn moduleResolution: "node" | "classic"
    "moduleResolution": "bundler",
    // baseUrl removed — dùng paths thay thế
    "paths": {
      "@/*": ["./src/*"]
    },
    "strict": true
  }
}

65. Migration path từ TS 5.x lên TS 7.0 như thế nào?

Lộ trình migrate khuyến nghị qua 3 bước:

Bước 1: TS 5.x → TS 6.0 (transition)

npm install typescript@6
  • Fix tất cả deprecation warning (các option sắp bị remove trong 7.0).
  • Bật strict: true cho project nếu chưa.
  • Chạy tsc --noEmit đảm bảo không lỗi.
  • Update các option: module, moduleResolution, target về giá trị TS 7.0 chấp nhận.

Bước 2: TS 6.0 → TS 7.0 (tsgo)

npm install typescript@7
  • Cập nhật tsconfig: xóa các option đã bị remove (baseUrl, preserveConstEnums, etc.).
  • Thêm types array rõ ràng nếu cần global types.
  • Switch từ tsc sang tsgo.
  • Verify tooling: IDE extension, CI pipeline, pre-commit hooks.

Bước 3: Verify & optimize

tsgo --noEmit  # type-check với tsgo
tsgo --checkers 8 --builders 4  # build với parallelism
  • Đo benchmark so với tsc cũ.
  • Tinh chỉnh --checkers dựa trên số CPU core của CI runner.

Có thể chạy song song TS 6 và TS 7 trong giai đoạn transition (xem Q67).

66. Tool nào compatible với tsgo?

ToolStatusGhi chú
Vite 6+✅ CompatibleDùng tsgo làm built-in type checker
VS Code✅ CompatibleCập nhật LSP extension cho tsgo
esbuild / swc✅ CompatibleVẫn dùng riêng để strip type, không bị ảnh hưởng
tsx✅ CompatibleDùng esbuild under the hood, không phụ thuộc compiler API
ts-node❌ Không hoạt độngPhụ thuộc programmatic API cũ của tsc
ts-jest❌ Không hoạt độngPhụ thuộc compiler API cũ
ts-morph❌ Không hoạt độngDựa trên compiler API cũ để thao tác AST
fork-ts-checker-webpack-plugin❌ Không hoạt độngPhụ thuộc tsc programmatic API

Giải pháp thay thế:

  • Thay ts-nodetsx (nhanh hơn, ESM-native).
  • Thay ts-jestvitest (dùng esbuild, nhanh hơn nhiều lần).
  • Nếu tool phụ thuộc programmatic API và chưa có replacement, giữ TS 6.x (xem Q67 để chạy song song).

67. Làm sao để chạy song song TS 6 và TS 7 trong cùng project?

Dùng npm package aliases để cài cả 2 phiên bản cùng lúc:

// package.json
{
  "devDependencies": {
    // TS 7 (default) cho IDE và dev build
    "typescript": "npm:typescript@^7.0.0",
    // TS 6 giữ lại cho tool chưa compatible
    "typescript6": "npm:typescript@^6.0.0"
  },
  "scripts": {
    "check": "tsgo --noEmit",              // TS 7
    "check:legacy": "tsc6 --noEmit",       // TS 6 fallback
    "build": "tsgo --checkers 4",
    "test": "vitest"                        // không cần ts-jest nữa
  }
}
# Dùng tsc6 cho TS 6
npx tsc6 --noEmit

# Dùng tsgo cho TS 7
npx tsgo --noEmit

CI strategy: chạy cả 2 checker (TS 6 + TS 7) để đảm bảo compatibility trong giai đoạn transition, dần dần bỏ TS 6 khi ecosystem đã sẵn sàng.

68. stableTypeOrdering là gì? Tại sao bắt buộc trong TS 7.0?

stableTypeOrdering là cơ chế đảm bảo thứ tự type trong union/intersection luôn deterministic — điều kiện tiên quyết cho parallel type-checking.

Vấn đề trước TS 7.0: Thứ tự member trong union type (vd: "a" | "b") có thể khác nhau giữa các lần chạy, phụ thuộc vào thứ tự file được parse trong pipeline tuần tự. Không ảnh hưởng đến type compatibility nhưng gây ra non-deterministic output.

TS 7.0 với parallelism: Các checker worker xử lý file song song, hoàn thành theo thứ tự khác nhau. Nếu không có stableTypeOrdering, kết quả merge union/intersection sẽ khác nhau giữa các lần chạy — dẫn đến:

  • Declaration file (.d.ts) không ổn định.
  • Cache invalidation sai.
  • CI false positive/negative.

Cách hoạt động: Union và intersection member được sắp xếp theo canonical order (alphabetical cho string literal, structural ordering cho object type) trước khi merge.

⚠️ Trade-off: Một số pattern hiếm dựa vào thứ tự type cũ có thể bị ảnh hưởng (vd: code dùng union member indexing). Nhưng hầu hết code không bị ảnh hưởng.

69. Programmatic API trong TS 7.0 thay đổi ra sao?

Programmatic API cũ bị xóa hoàn toàn trong TS 7.0 — đây là breaking change lớn nhất cho ecosystem.

API cũ bị remove (TS 6.x trở về trước):

// TẤT CẢ function này bị xóa trong TS 7.0
import ts from "typescript";

ts.createProgram(...)       // ❌
ts.createSourceFile(...)    // ❌
ts.createCompilerHost(...)  // ❌
ts.transform(...)           // ❌
ts.factory.createCall(...)  // ❌
// ... toàn bộ ts.* API

Lý do: API cũ được thiết kế cho kiến trúc single-thread, monolithic — không thể map sang kiến trúc multi-thread worker pool của tsgo.

API mới (dự kiến TS 7.1+):

  • Thiết kế lại hoàn toàn: async-first, streaming, worker-aware.
  • API mới tập trung vào các use case chính: programmatic type-check, emit, transform.
  • Không còn cho phép thao tác AST trực tiếp như trước (để đảm bảo thread safety).

Tác động:

  • ts-morph, ts-node, ts-jest, fork-ts-checker-webpack-pluginkhông hoạt động với TS 7.0.
  • Các tool này cần được rewrite để dùng API mới (dự kiến TS 7.1) hoặc fallback về TS 6.x.

70. Có nên migrate lên TS 7.0 ngay khi stable không?

Tùy ngữ cảnh — không có câu trả lời một-size-fits-all.

Tình huốngKhuyến nghịLý do
App nội bộ / startup✅ NÊN migrate sớmHưởng speed 10x, DX tốt hơn, ít phụ thuộc ecosystem tooling
Library public⚠️ THẬN TRỌNGĐợi ecosystem tooling ổn định, test downstream user
Monorepo lớn (>100k LOC)✅ CÂN NHẮC sớmSpeed boost đáng giá nhất với codebase lớn. Verify CI/CD pipeline kỹ
Đang dùng ts-node / ts-jest⚠️ CHỜChưa có replacement ổn định. Chạy song song TS 6 (xem Q67)
Team nhỏ, ít test⚠️ CHỜRủi ro cao nếu tooling break mà không có fallback

Lộ trình an toàn:

  1. Tạo branch riêng, upgrade lên TS 7.0.
  2. Chạy benchmark (type-check time, build time) để đo improvement.
  3. Verify tất cả tooling: IDE, lint, test, CI, deploy.
  4. Nếu tất cả OK → merge. Nếu tooling break → đợi hoặc dùng Q67 (song song).

71. TS 7.0 có thay đổi gì về type system không?

Type system của TS 7.0 tương thích ngược với TS 6.x — không có breaking change lớn về type-level. Tuy nhiên có một số thay đổi đáng chú ý:

Thay đổi về type system:

  • Unicode template literal fix: Sửa bug với surrogate pairs và combining characters trong template literal type. Trước đây một số ký tự Unicode đa byte bị xử lý sai khi dùng trong infer pattern.
  • stableTypeOrdering bắt buộc: Union/intersection luôn có thứ tự deterministic (xem Q68). Không ảnh hưởng đến tính đúng đắn của type, nhưng .d.ts output có thể thay đổi.
  • Reduced context sensitivity: Giảm một số edge case ambiguous parse — code vốn parse sai do context sensitivity giờ được bắt lỗi compile-time.

Không thay đổi:

  • Conditional types, mapped types, infer — hoạt động y hệt.
  • Generic constraint và inference.
  • Discriminated union narrowing.
  • Template literal type (ngoại trừ Unicode fix).

Kết luận: Nếu code của bạn type-check OK với TS 6.0 strict mode, gần như chắc chắn sẽ OK với TS 7.0. Thay đổi chủ yếu ở compiler infrastructure, không phải type system.

72. types: [] default mới ảnh hưởng gì?

Từ TS 7.0, types mặc định là [] — trình biên dịch KHÔNG tự động scan @types/* trong node_modules nữa.

Trước TS 7.0:

// tsconfig.json (TS 5.x / 6.x)
{
  "compilerOptions": {
    // Không set "types" → tự động scan TẤT CẢ @types/*
    // Jest, Node, React... tự động có sẵn dưới dạng global type
  }
}
// Code cũ — dùng global type mà không cần import
describe("test", () => { ... });  // ✅ auto từ @types/jest
process.env.NODE_ENV;             // ✅ auto từ @types/node

TS 7.0:

{
  "compilerOptions": {
    // "types": [] là default — KHÔNG scan @types/*
    // Phải khai báo rõ
    "types": ["node", "jest", "react-dom"]
  }
}
// Nếu không set "types": ["jest"] → lỗi
describe("test", () => { ... });  // ❌ Cannot find name 'describe'

Lợi ích:

  • Type-checking scope chính xác hơn, tránh xung đột global type từ các package không liên quan.
  • Build nhanh hơn (không scan hàng trăm @types package).
  • Explicit dependency — dễ audit type nào đang được dùng.

Migration fix đơn giản: Thêm "types": ["node", "jest", ...] — liệt kê các @types package bạn thực sự cần.

73. Node.js type stripping vs tsgo — dùng cái nào?

Hai công cụ phục vụ 2 mục đích khác nhau — hiểu rõ để chọn đúng cho từng ngữ cảnh.

Node.js --strip-types (Node 23+)tsgo (TS 7.0)
Type-check?❌ Không — chỉ xóa syntax TS✅ Có — full type-check
Tốc độGần như instant (chỉ parse + strip)Nhanh hơn tsc 10x, nhưng vẫn chậm hơn strip
OutputJS (giữ nguyên format, chỉ xóa annotation)JS (compile đầy đủ: downlevel, enum, decorator...)
RuntimeNode.js nativeGo binary độc lập
Phù hợpDev loop nhanh, hot reloadCI, production build, type safety

Best practice kết hợp:

// package.json
{
  "scripts": {
    // Dev: nhanh nhất có thể, không cần type-check mỗi lần save
    "dev": "node --strip-types --watch src/index.ts",

    // CI / pre-commit: type-check với tsgo (nhanh 10x)
    "typecheck": "tsgo --noEmit",

    // Production build: esbuild/swc strip type + tsgo check
    "build": "tsgo --noEmit && esbuild src/index.ts --bundle --outdir=dist"
  }
}

Nguyên tắc:

  • Dev loop → Node.js --strip-types (tốc độ tối đa, không cần type-check từng lần save).
  • CI / pre-pushtsgo --noEmit (bắt lỗi type trước khi merge).
  • Production build → tsgo check + esbuild/swc bundle (an toàn + nhanh).
Tiếp theo chủ đề: OOP

© 2026 .NET Fresher Guide. All rights reserved.

Về Trang Web

Hướng dẫn toàn diện để chuẩn bị phỏng vấn vị trí .NET Fresher với nội dung từ lý thuyết đến thực hành.