Tài liệu TypeScript
Tài liệu tham khảo TypeScript ngắn gọn, đi kèm ví dụ. Đọc khái niệm, xem code, rồi luyện tập trong một hành trình Coddy.
Bắt đầu khóa họcBắt đầu
- TypeScript là gìTypeScript là JavaScript có kiểu tĩnh. Bạn gắn kiểu cho các giá trị, trình biên dịch kiểm tra chúng trước khi code chạy, và kết quả là JavaScript thuần chạy được trên mọi trình duyệt, trên Node.js, Deno và Bun.
- TypeScript vs JavaScriptTypeScript là JavaScript cộng thêm một hệ thống kiểu tĩnh được kiểm tra trước khi code chạy. So sánh hai ngôn ngữ song song: cú pháp, những lỗi bộ kiểm tra kiểu bắt được, bước build, tốc độ khi chạy, độ khó khi học và cách chuyển một dự án JavaScript sang TypeScript.
- Cài đặt TypeScriptCài TypeScript bằng npm làm dev dependency của dự án, kiểm tra phiên bản bằng npx tsc --version, tạo tsconfig.json bằng tsc --init và biên dịch tệp đầu tiên. Có cả cài đặt toàn cục, pnpm, Yarn, Bun và những lỗi hay gặp.
- Chạy TypeScriptNăm cách chạy một tệp .ts: biên dịch bằng tsc rồi chạy JavaScript, chạy thẳng bằng node file.ts (type stripping), dùng tsx hoặc ts-node, hoặc dùng Deno và Bun. Cách nào kiểm tra kiểu, mỗi cách hỗ trợ cú pháp nào và nên chọn cách nào.
- tsconfig.jsontsconfig.json đánh dấu một thư mục là dự án TypeScript và đặt các tùy chọn cho trình biên dịch. Các tùy chọn quan trọng (target, module, moduleResolution, strict, rootDir, outDir, include, lib, types, noEmit, skipLibCheck), một cấu hình khởi đầu nên dùng, extends và những gì TypeScript 7 đã thay đổi.
- TypeScript 7TypeScript 7 là trình biên dịch TypeScript được viết lại bằng Go thành chương trình native: nhanh hơn khoảng mười lần, vẫn lệnh tsc và vẫn ngôn ngữ cũ. Những gì thay đổi với người dùng (mặc định mới, tùy chọn bị xóa, JavaScript API chưa có), công cụ nào vẫn cần TypeScript 6 và cách nâng cấp.
- Chú thích (comment)TypeScript dùng chú thích // và /* */ của JavaScript, cùng chú thích JSDoc /** */ mà trình soạn thảo hiển thị khi rê chuột. TypeScript còn đọc một vài chú thích đặc biệt: @ts-expect-error, @ts-ignore, @ts-nocheck, @ts-check và các chỉ thị /// <reference>.
- TypeScript vs PythonTypeScript và Python đều là ngôn ngữ bậc cao có garbage collection, nhưng TypeScript kiểm tra kiểu trước khi code chạy, còn type hint của Python là tùy chọn và bị bỏ qua lúc chạy. So sánh song song về kiểu, runtime, tốc độ, hệ sinh thái và ứng dụng, với cùng một chương trình viết bằng cả hai.
Kiểu cơ bản
- Kiểu cơ bảnCác kiểu có sẵn của TypeScript: string, number, boolean, bigint, symbol, null và undefined, cùng cái nhìn nhanh về mảng và đối tượng. Cách viết chú thích kiểu, vì sao không có kiểu số nguyên, và vì sao bạn viết string chứ không phải String.
- Suy luận kiểuTypeScript tự suy ra phần lớn kiểu từ các giá trị bạn viết. Tìm hiểu kiểu được suy ra cho biến, let và const, đối tượng, mảng và giá trị trả về, cách callback nhận kiểu từ ngữ cảnh, và những chỗ bạn vẫn cần chú thích kiểu.
- ChuỗiLàm việc với chuỗi trong TypeScript: nội suy bằng template literal, chuỗi nhiều dòng, kiểm tra một chuỗi có chứa chuỗi con không, các phương thức thường dùng cùng kiểu chúng trả về, và string literal type.
- String sang numberChuyển chuỗi thành số trong TypeScript bằng Number(), parseInt(), parseFloat() hoặc dấu + một ngôi, xem mỗi cách xử lý các đầu vào như "42px", "" và "1e3" ra sao, kiểm tra NaN an toàn, và chuyển số ngược lại thành chuỗi.
- MảngCách khai báo kiểu cho mảng trong TypeScript: T[] và Array<T>, mảng đối tượng, mảng chứa nhiều kiểu, mảng readonly, và map, filter, reduce, find trả về gì. Thêm cả cái bẫy includes với mảng literal.
- TupleTuple trong TypeScript là một mảng có số phần tử cố định, kiểu của mỗi phần tử được biết theo vị trí, như [string, number]. Tìm hiểu cú pháp, phần tử có tên, phần tử tùy chọn và rest, tuple readonly và as const, trả về tuple từ hàm, và tuple khác mảng ra sao.
- Kiểu objectCách khai báo kiểu cho object trong TypeScript: kiểu object viết trực tiếp, thuộc tính tùy chọn với ?, thuộc tính readonly, object lồng nhau, phương thức, kiểm tra thuộc tính thừa, và sự khác nhau giữa object, {} và Object.
- EnumEnum trong TypeScript là một tập hằng số có tên, ví dụ enum Direction { Up, Down }. Tìm hiểu enum số và enum chuỗi, đoạn JavaScript mà một enum được biên dịch thành, ánh xạ ngược, cách duyệt qua enum, const enum, và khi nào nên dùng union các chuỗi literal hoặc đối tượng as const thay cho enum.
Kiểu đặc biệt
- Literal typeLiteral type là kiểu chỉ có đúng một giá trị, như "GET" hay 404. Tìm hiểu literal type cho chuỗi, số và boolean, union của các literal, vì sao let bị mở rộng kiểu còn const thì không, as const làm gì và const type parameter.
- any và unknownCả any và unknown đều nhận mọi giá trị. any tắt kiểm tra kiểu cho giá trị đó, còn unknown buộc bạn kiểm tra giá trị trước khi dùng. Tìm hiểu điểm khác nhau, cách thu hẹp unknown, noImplicitAny và những chỗ any lén lọt vào code đã có kiểu.
- Kiểu nevernever là kiểu không có giá trị nào. Đó là kiểu trả về của các hàm không bao giờ kết thúc, là kiểu còn lại khi việc thu hẹp đã loại hết mọi trường hợp, và là công cụ đằng sau phép kiểm tra switch đầy đủ. Tìm hiểu never đến từ đâu và khác void thế nào.
- null và undefinedKhi bật strictNullChecks, null và undefined là các kiểu riêng mà TypeScript buộc bạn phải xử lý. Tìm hiểu cách kiểm tra chúng, optional chaining (?.), dấu hai chấm hỏi (??) và ??=, cùng sự khác nhau giữa thuộc tính tùy chọn và | undefined.
- Non-null assertion (!)Dấu chấm than sau một giá trị, như user!, là toán tử non-null assertion: nó bỏ null và undefined khỏi kiểu mà không kiểm tra gì lúc chạy. Tìm hiểu x! làm gì, các dạng definite assignment let x!: T và prop!: T, vì sao chúng rủi ro, và những cách an toàn hơn.
Interface và type alias
- InterfaceInterface đặt tên cho hình dạng của một object: object có những thuộc tính nào và mỗi thuộc tính mang kiểu gì. Tìm hiểu cách khai báo interface, thuộc tính tùy chọn và readonly, phương thức, index signature, kế thừa, implement trong lớp, declaration merging, interface generic và cách đặt giá trị mặc định.
- Type aliasType alias đặt tên cho bất kỳ kiểu nào bằng từ khóa type: hình dạng đối tượng, union, tuple, hàm, generic và kiểu đệ quy. Tìm hiểu cú pháp, cách viết từng dạng, và vì sao alias chỉ là một cái tên chứ không phải một kiểu mới, tách biệt.
- Interface và typeinterface và type đều mô tả được hình dạng object, và phần lớn trường hợp dùng cái nào cũng được. Tìm hiểu những khác biệt thật sự: declaration merging, union và mapped type, extends và intersection, index signature ngầm định, cách báo lỗi và hiệu năng trình biên dịch, kèm một quy tắc rõ ràng để chọn.
- Từ khóa extendsTừ khóa extends xây dựng một kiểu từ một kiểu khác. Tìm hiểu cách mở rộng một interface (từ một hoặc nhiều interface), mở rộng type alias bằng &, ghi đè kiểu của thuộc tính, thay thế thuộc tính bằng Omit, và ý nghĩa của extends trong lớp, ràng buộc generic và conditional type.
- Union typeMột union type như string | number nghĩa là giá trị có thể là một trong nhiều kiểu. Tìm hiểu những gì bạn làm được với một union (chỉ những gì mọi thành viên đều hỗ trợ), cách thu hẹp nó, union của literal và kiểu đối tượng, cùng sự khác nhau giữa (A | B)[] và A[] | B[].
- Intersection typeIntersection type A & B mô tả một giá trị đồng thời là A và B, nên nó có mọi thành viên của cả hai. Tìm hiểu cách kết hợp kiểu object bằng &, vì sao thuộc tính xung đột trở thành never, vì sao intersection của các union chỉ giữ thành viên chung, và khi nào nên dùng extends.
- Discriminated unionDiscriminated union là union của các kiểu đối tượng có chung một thuộc tính nhãn dạng literal, như kind hoặc status. Kiểm tra nhãn sẽ thu hẹp kiểu của cả đối tượng. Tìm hiểu mẫu này, cách thu hẹp kiểu bằng switch, kiểm tra đầy đủ với never, và cách mô hình hóa kết quả API, trạng thái request và state machine.
Hàm
- HàmCách khai báo kiểu cho hàm trong TypeScript: chú thích kiểu cho mọi tham số, chú thích hoặc để suy ra kiểu trả về, dùng void cho hàm không trả về gì, và khai báo kiểu cho arrow function, biểu thức hàm, hàm async và tham số this.
- Kiểu hàmCách viết kiểu của một hàm trong TypeScript: cú pháp mũi tên (a: number) => string, type alias cho hàm, khai báo kiểu cho arrow function và callback, call signature và construct signature, và vì sao kiểu Function quá lỏng lẻo.
- Tham số tùy chọnĐánh dấu tham số TypeScript là tùy chọn bằng ?, gán giá trị mặc định cho nó, hoặc gom số lượng đối số bất kỳ bằng tham số rest. Gồm quy tắc thứ tự, bỏ qua so với undefined, options object và tham số tùy chọn trong kiểu hàm.
- Nạp chồng hàmNạp chồng hàm (function overload) trong TypeScript cho phép một hàm có nhiều chữ ký gọi, mỗi chữ ký có kiểu trả về riêng. Tìm hiểu mẫu overload signature kèm phần cài đặt, các quy tắc trình biên dịch kiểm tra, khi nào tham số union tốt hơn, và overload trong lớp.
Thu hẹp kiểu và kiểm tra kiểu
- Thu hẹp kiểuThu hẹp kiểu là cách TypeScript biến một kiểu rộng như string | number thành một kiểu cụ thể bên trong if, switch hay sau một lệnh return sớm. Mọi dạng thu hẹp ở cùng một chỗ: typeof, truthiness, so sánh bằng, in, instanceof, phép gán, type predicate và discriminated union.
- Toán tử typeoftypeof có hai vai trò trong TypeScript. Trong code, nó là toán tử JavaScript trả về "string", "number", "object" và các giá trị khác lúc chạy, và TypeScript thu hẹp kiểu dựa trên nó. Trong một kiểu, nó là truy vấn kiểu sao chép kiểu của một biến, như trong keyof typeof obj và ReturnType<typeof fn>.
- Toán tử instanceofinstanceof kiểm tra lúc chạy xem một object có được tạo từ một lớp hay không, và TypeScript thu hẹp biến về đúng lớp đó. Cách nó hoạt động với lớp của bạn và các lớp con của Error, vì sao nó không kiểm tra được interface hay type alias, và những chỗ nó cho kết quả bất ngờ.
- Type guardType guard là một phép kiểm tra lúc chạy mà TypeScript hiểu được. Tìm hiểu các guard dựng sẵn, cách tự viết guard với type predicate value is Type, cách kiểm tra một đối tượng có thuộc một kiểu không, hàm assertion với asserts, và cách xác thực dữ liệu unknown.
- Type assertionTừ khóa as bảo TypeScript coi một giá trị là một kiểu khác. Đây không phải ép kiểu: không có gì được chuyển đổi hay kiểm tra lúc chạy. Tìm hiểu cú pháp as và dấu ngoặc nhọn, những gì trình biên dịch cho phép, assertion kép qua unknown, và khi nào type guard là công cụ tốt hơn.
- Toán tử satisfiesToán tử satisfies kiểm tra một giá trị có khớp với một kiểu hay không mà không thay đổi kiểu được suy luận của giá trị đó. Tìm hiểu satisfies làm gì, so sánh nó với chú thích kiểu và với as (cùng một đối tượng viết theo ba cách), cách kết hợp với as const, và vì sao nó hợp với đối tượng cấu hình.
Lớp
- Lớp (class)Class trong TypeScript là class JavaScript có thêm kiểu cho thuộc tính, phương thức và hàm khởi tạo. Tìm hiểu cách khai báo thuộc tính và strictPropertyInitialization hoạt động, cách gán kiểu cho this, getter và setter, thành viên static, implements, và vì sao một class cũng là một kiểu.
- Hàm khởi tạoCách gán kiểu cho hàm khởi tạo của class trong TypeScript: tham số có kiểu và tham số tùy chọn, parameter property như constructor(private name: string), thứ tự khởi tạo thuộc tính, overload cho hàm khởi tạo, gọi super trong class con, hàm khởi tạo private và kiểu hàm khởi tạo với new.
- Access modifierTypeScript có ba access modifier là public, private và protected, cùng với readonly. Tìm hiểu mỗi loại cho phép gì, vì sao private của TypeScript chỉ được kiểm tra khi biên dịch còn field #private của JavaScript được áp dụng lúc runtime, và nên chọn loại nào.
- Kế thừaKế thừa lớp trong TypeScript: extends và super, ghi đè phương thức với kiểu tương thích, từ khóa override và noImplicitOverride, thành viên protected, khai báo lại field bằng declare, và khi nào implements là lựa chọn tốt hơn.
- Abstract classAbstract class trong TypeScript là lớp cơ sở không thể tạo instance trực tiếp và có thể để lại phương thức cho lớp con triển khai. Tìm hiểu phương thức và thuộc tính abstract, mẫu template method, kiểu hàm khởi tạo abstract và khi nào interface là lựa chọn tốt hơn.
- DecoratorDecorator là các hàm bao bọc hoặc thay thế thành viên của class bằng cú pháp @. Tìm hiểu các decorator chuẩn mà TypeScript hỗ trợ không cần cờ nào (class, method, getter, field và accessor), decorator factory, addInitializer, và chúng khác gì experimentalDecorators kiểu cũ mà Angular và NestJS dùng.
Generic
- GenericGeneric cho phép một hàm, interface, type hay lớp làm việc với nhiều kiểu mà vẫn giữ chúng gắn kết với nhau: thứ đi vào quyết định thứ đi ra. Tìm hiểu hàm generic, suy luận đối số kiểu, nhiều tham số kiểu, interface và lớp generic, giá trị mặc định, và khi nào không nên dùng generic.
- Ràng buộc genericRàng buộc generic, T extends Something, giới hạn những kiểu mà một tham số kiểu chấp nhận và cho phép hàm dùng những gì ràng buộc đảm bảo. Bài viết gồm extends với hình dạng đối tượng và interface, K extends keyof T để truy cập thuộc tính an toàn, ràng buộc với kiểu nguyên thủy, và các lỗi bạn sẽ gặp.
Toán tử kiểu
- Toán tử keyofkeyof nhận một kiểu đối tượng và trả về union các tên thuộc tính của nó. Tìm hiểu keyof với interface, keyof typeof cho đối tượng thường, truy cập thuộc tính có kiểu bằng generic, index signature (string | number), và vì sao Object.keys trả về string[].
- Indexed access typeIndexed access type đọc kiểu của một thuộc tính từ một kiểu khác: Person["age"] là number. Tìm hiểu T["key"], khóa dạng union, T[keyof T], T[number] cho phần tử mảng, chỉ số tuple và (typeof arr)[number] để biến một mảng const thành union.
- Mapped typeMapped type tạo một kiểu đối tượng mới bằng cách lặp qua các khóa: { [K in keyof T]: ... }. Tìm hiểu cú pháp, modifier readonly và ? với + và -, đổi tên khóa bằng as, lọc khóa, và cách Partial, Readonly, Required, Pick, Record được viết.
- Conditional typeConditional type chọn một trong hai kiểu dựa trên một phép kiểm tra: T extends U ? X : Y. Tìm hiểu cú pháp, cách conditional type phân phối trên union (và cách ngăn điều đó), cách trích xuất kiểu bằng infer, và cách tự viết ReturnType.
- Template literal typeTemplate literal type tạo ra string literal type bằng đúng cú pháp backtick của template string trong JavaScript: `on${Capitalize<E>}`. Tìm hiểu cú pháp, cách union nhân lên, Uppercase và Capitalize, các mẫu như `${number}px`, getter với mapped type, và phân tích chuỗi bằng infer.
- Branded typeBranded type là một kiểu nguyên thủy mang một thẻ vô hình, như string & { readonly __brand: "UserId" }, để một UserId không thể được truyền vào chỗ cần OrderId. Tìm hiểu cách brand hoạt động, hàm khởi tạo có kiểm tra dữ liệu, helper Brand dạng generic, brand bằng unique symbol và số có brand.
Utility type
- Utility typeMọi utility type có sẵn của TypeScript ở cùng một chỗ: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ReturnType, Awaited, các kiểu chuỗi và nhiều hơn nữa, mỗi kiểu kèm mô tả một dòng và ví dụ chạy được.
- RecordRecord<K, V> là kiểu object có khóa kiểu K và mọi giá trị đều kiểu V. Tìm hiểu Record với khóa string và khóa union (mọi khóa đều bắt buộc), Partial<Record>, duyệt Record với khóa có kiểu, cái bẫy khóa không tồn tại, và khi nào nên dùng index signature hoặc Map thay thế.
- Partial và RequiredPartial<T> biến mọi thuộc tính của T thành tùy chọn, đúng kiểu của một object cập nhật hay patch. Tìm hiểu Partial trong hàm cập nhật, vì sao nó chỉ ở mức nông, cách viết DeepPartial, cái bẫy undefined tường minh, và kiểu ngược lại là Required<T>.
- OmitOmit<T, K> tạo một kiểu có mọi thuộc tính của T trừ các khóa K. Tìm hiểu Omit với một hoặc nhiều khóa, ghi đè kiểu thuộc tính, xóa thuộc tính lúc chạy, Omit so với Exclude và Pick, vì sao Omit nhận cả khóa không tồn tại, Omit chặt chẽ và Omit trên kiểu union.
- PickPick<T, K> tạo một kiểu chỉ gồm các thuộc tính của T có khóa nằm trong K. Tìm hiểu Pick với một hoặc nhiều khóa, cách nó kiểm tra khóa, Pick so với Omit, chọn từ kiểu lồng nhau, hàm pick() có kiểu và chọn thuộc tính theo kiểu giá trị.
- readonly và ReadonlyModifier readonly và utility type Readonly<T> ngăn code gán lại thuộc tính. Tìm hiểu thuộc tính readonly và trường của lớp, Readonly<T>, mảng chỉ đọc (readonly T[] và ReadonlyArray), ReadonlyMap và ReadonlySet, vì sao readonly chỉ ở mức nông và chỉ có tác dụng lúc biên dịch, và so sánh với Object.freeze và as const.
- Exclude và ExtractExclude, Extract và NonNullable lọc các thành viên của một union type. Tìm hiểu mỗi kiểu giữ lại và loại bỏ những gì, cách chọn thành viên của union theo hình dạng, cách chúng được xây dựng từ conditional type, và chúng khác Omit và Pick ra sao.
- ReturnType và ParametersReturnType, Parameters, ConstructorParameters, InstanceType và Awaited lấy ra kiểu từ hàm, lớp và promise. Tìm hiểu cách dùng chúng với typeof, cách lấy kiểu kết quả của hàm async, chuyện gì xảy ra với overload và generic, và ReturnType được xây dựng bằng infer như thế nào.
Vòng lặp và collection
- Vòng lặpMọi cách lặp trong TypeScript và kiểu mà mỗi cách mang lại: vòng lặp for cổ điển, for...of trên mảng, Map và chuỗi, for...in với khóa kiểu string, forEach (không break, không await), lặp qua khóa đối tượng có kiểu, và while.
- Câu lệnh switchCâu lệnh switch trong TypeScript: cú pháp, cách mỗi case thu hẹp một union type, switch kiểm tra đủ mọi trường hợp để không biên dịch được khi thiếu case, mẫu switch (true), fallthrough và phạm vi khối lệnh.
- MapCách dùng Map trong TypeScript: tạo Map<K, V> có kiểu, vì sao get trả về V | undefined, set, has và delete, lặp theo thứ tự thêm vào, dùng đối tượng làm khóa, chuyển đổi qua lại với đối tượng và JSON, so sánh Map, object và Record, và khai báo kiểu cho array.map().
- Từ điển (dictionary)TypeScript không có class dictionary hay hashmap riêng; bạn gán kiểu cho một bảng tra cứu khóa và giá trị bằng index signature, Record<K, V> hoặc Map<K, V>. Tìm hiểu từng cách, cách kiểm tra một khóa có tồn tại không, cách thêm, xóa, duyệt, và vì sao noUncheckedIndexedAccess quan trọng với từ điển.
Bất đồng bộ và lỗi
- PromiseCách khai báo kiểu cho promise trong TypeScript: kiểu Promise<T>, khai báo kiểu cho new Promise và resolve, then thay đổi kiểu thế nào, vì sao catch cho bạn any, Promise.all với kết quả tuple, kiểu kết quả của Promise.allSettled, và bọc API dùng callback thành promise có kiểu.
- Async/AwaitCách async và await được khai báo kiểu trong TypeScript: hàm async trả về Promise<T>, await mở nó ra, lỗi được bắt bằng try/catch, top-level await cần ES module, cùng với khác biệt giữa await lần lượt, await song song và cái bẫy forEach.
- Xử lý lỗiXử lý lỗi trong TypeScript: vì sao biến của catch có kiểu unknown, cách thu hẹp nó bằng instanceof Error, cách ném lỗi, viết lớp lỗi tùy chỉnh với name và cause, và mẫu kiểu Result cho những lỗi bạn đã lường trước.
- SleepTypeScript không có sleep dựng sẵn, nhưng chỉ một dòng code là bạn có ngay: một hàm trả về Promise<void> được setTimeout resolve. Tìm hiểu cách await nó, tạm dừng trong vòng lặp, thử lại sau một khoảng chờ, hủy sleep, và vì sao JavaScript không có sleep chặn luồng.
Module và công cụ
- ModuleMọi tệp TypeScript có import hoặc export ở cấp cao nhất đều là một module. Tìm hiểu named export và default export, import type và export type, cách thiết lập module quyết định đầu ra là ES module hay CommonJS, và vì sao node16 và nodenext đòi đuôi .js trong câu lệnh import.
- NamespaceNamespace trong TypeScript gom giá trị và kiểu dưới một tên và được biên dịch thành một đối tượng thường. Tìm hiểu cú pháp, cách namespace hợp nhất với nhau và với hàm, lớp, vì sao ES module đã thay thế chúng, và những nơi bạn vẫn gặp chúng: tệp khai báo và global augmentation.
- Tệp khai báoTệp .d.ts mô tả kiểu của code JavaScript mà không chứa chút code nào, và từ khóa declare làm điều tương tự bên trong một tệp .ts. Tìm hiểu cách tệp khai báo được sinh ra, vai trò của các package @types, cách gán kiểu cho một module chưa có kiểu, và cách declare global cùng module augmentation mở rộng các kiểu có sẵn.
- Strict modestrict: true trong tsconfig.json bật cả một nhóm kiểm tra kiểu: noImplicitAny, strictNullChecks, strictPropertyInitialization và năm cờ khác. Xem mỗi cờ bắt được lỗi gì, cách bật strict mode trong một dự án có sẵn, và những cờ hữu ích mà strict không bao gồm.
- JSONJSON.parse trả về any, nên TypeScript tin mọi kiểu bạn gán cho kết quả. Tìm hiểu cách khai báo kiểu cho JSON sau khi parse, kiểm tra dữ liệu bằng type guard, chuyển một mẫu JSON thành interface, import tệp .json và JSON.stringify làm gì với Date, Set và undefined.
Tìm hiểu sâu hơn
- Best practiceTám thói quen TypeScript giúp ngăn bug thật: luôn bật strict, dùng unknown thay cho any, để suy luận kiểu làm việc, ưu tiên union hơn enum, kiểm tra config bằng satisfies, mô hình hóa state bằng discriminated union, tránh ! và as, và đặt dữ liệu là readonly. Mỗi quy tắc đi kèm ví dụ trước và sau chạy được.
- Câu hỏi phỏng vấn25 câu hỏi phỏng vấn TypeScript với câu trả lời ngắn, chính xác và có code, chia từ cơ bản đến nâng cao: any và unknown, interface và type, generic, thu hẹp kiểu, utility type, mapped type và conditional type, structural typing, tsconfig và TypeScript 7.