Tổng hợp 75 câu hỏi phỏng vấn TypeScript kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
TypeScript là superset của JavaScript có kiểu tĩnh, biên dịch ra JavaScript thuần. Cùng đoạn đó trong JavaScript chạy bình thường và trả về '0102' — một bug âm thầm chỉ lộ ra khi người dùng gặp. Bốn lợi ích, xếp theo mức tác động…
Type annotation là khai báo kiểu tường minh cho biến, parameter, return value: let name: string = 'John'. TypeScript cũng có type inference tự suy luận kiểu từ giá trị gán. Annotation thường chỉ cần cho function parameters, return types, và khi inference không đủ…
Ba kiểu ở ba vị trí đối lập nhau trong hệ thống kiểu. Gán giá trị vào Gán ra biến khác An toàn ------------ any mọi thứ mọi thứ không unknown mọi thứ chỉ sau khi thu hẹp có never không gì mọi thứ —…
A B là hoặc, A & B là và. Điểm hay nhầm — union thu hẹp cái dùng được, intersection mở rộng: Muốn dùng thuộc tính riêng của union thì phải thu hẹp kiểu trước (typeof, in, discriminated union). Hai đặc điểm của intersection hay…
Literal type là kiểu chỉ nhận đúng một giá trị cụ thể. Dùng thay enum mà không sinh code lúc chạy: Lưu ý — TypeScript mở rộng kiểu khi dùng let: Giữ literal bằng as const: Chốt: literal type là nền tảng của discriminated union…
Type narrowing là thu hẹp type trong code branch dựa trên kiểm tra. TypeScript tự động narrow trong if/else, switch, ternary.
as ghi đè suy luận kiểu của TypeScript lúc biên dịch, và không kiểm tra gì lúc chạy. Hai trường hợp dùng hợp lý: 1. DOM — TypeScript chỉ biết HTMLElement, bạn biết cụ thể hơn. 2. as const — giữ literal type, đây là…
! nói với TypeScript rằng giá trị chắc chắn không phải null/undefined — và cũng không kiểm tra gì lúc chạy. Các cách thay thế, xếp theo mức an toàn giảm dần: Còn một dạng khác của ! — definite assignment assertion trên khai báo…
Tuple là array với số lượng và kiểu phần tử cố định. Phần tử có thể có tên. Hỗ trợ optional (?) và rest elements. Thường dùng cho function return nhiều giá trị, CSV rows, React useState.
Enum khai báo tập hợp named constants. Numeric enum tự động assign 0,1,2... có reverse lookup nhưng gây footgun (Direction[0] = 'Up'). String enum cần gán tường minh, dễ debug hơn, không có reverse lookup.
satisfies (TS 4.9) kiểm tra type mà không mở rộng type declaration. Khác as: satisfies vẫn infer type cụ thể nhất có thể và báo lỗi nếu không match. Ví dụ: const config = {...} satisfies Config - TS check config đúng Config nhưng giữ…
as const biến values thành readonly literal types cụ thể nhất. Array thành readonly tuple, object properties thành readonly literal types. Ví dụ: const dirs = ['left', 'right'] as const tạo type readonly ['left', 'right'] thay string[]. Hữu ích để tạo strongly-typed constants.
"strict": true bật một nhóm cờ kiểm tra chặt cùng lúc: Hai cờ có tác động lớn nhất: useUnknownInCatchVariables (TS 4.4) hay gây bối rối khi nâng cấp dự án cũ: Chuyển dự án JavaScript sang TypeScript thì bật dần, không bật hết một lần:…
Cả hai đều mô tả shape (cấu trúc) của object; khác nhau ở những gì làm được ngoài object và khả năng gộp khai báo. interface type --------- Mô tả object có có Union / tuple / conditional không có Gộp khai báo (merging) có…
Interface: interface Child extends Parent { ... } và extends nhiều: extends A, B. Type: type Combined = A & B (intersection). Interface có thể extend type và ngược lại. extends kiểm tra compatibility (không thể re-declare incompatible property), còn & intersection merge tất cả.
Index signature cho phép object có keys không biết trước. Tất cả explicit properties phải compatible với index signature type.
Optional property (prop?: Type) có thể có hoặc không, type là Type undefined khi access. Khác với prop: Type undefined — cái sau vẫn yêu cầu key có mặt khi tạo object. readonly property không thể reassign sau khởi tạo (chỉ compile time). Readonly<T làm…
Discriminated union là union trong đó mỗi member có common literal property (discriminant). TypeScript narrow type tự động khi check discriminant. Giúp type-safe handling cases khác nhau, TypeScript sẽ báo lỗi nếu thiếu case.
TypeScript hỗ trợ recursive type aliases. Hữu ích cho tree structures, nested JSON, linked lists. Interface luôn hỗ trợ recursive (vì là named type), type alias cũng hỗ trợ từ TS 3.7.
TypeScript kiểm tra extra properties khi assign object literal trực tiếp vào typed variable. Nhưng assign qua biến trung gian không bị check — đây là behavior khá bất ngờ. Behavior này giúp phát hiện typos trong config objects.
Generics cho phép tạo components (functions, classes, interfaces) hoạt động với nhiều kiểu dữ liệu mà vẫn type-safe. Thay dùng any, dùng type parameter <T. Tái sử dụng code mà không mất type information.
Constraints giới hạn type parameter phải extend một type cụ thể, ngăn dùng với types không compatible.
keyof T trả về union type của tất cả keys của T: keyof {a: number, b: string} cho ra 'a' 'b'. Dùng với generics để type-safe property access: function get<T, K extends keyof T(obj: T, key: K): T[K] đảm bảo key tồn tại và return…
Hai utility type trích ra danh sách tham số dưới dạng tuple. Bên trong cả hai đều dùng infer: Công dụng thực tế nhất — bọc một hàm mà không phải khai lại signature: Lấy một tham số riêng lẻ bằng chỉ số: Lưu ý:…
Hàm có thể có nhiều type params. Inference hoạt động độc lập cho mỗi param. Đặt tên rõ ràng (TKey, TValue) thay vì chỉ T, U, V khi có nhiều params.
Partial<T làm tất cả properties của T thành optional. Required<T làm tất cả optional thành required. Cả hai chỉ shallow.
Record<Keys, Value tạo object type với specific keys và value type. Khác index signature: Keys có thể là specific union (yêu cầu tất cả keys có mặt, không optional). Rõ ràng hơn và type-safe hơn index signature.
Pick<T, K tạo type chỉ với subset of properties K từ T: Pick<User, 'id' 'name' chỉ giữ lại id và name. Omit<T, K là ngược lại: tạo type với tất cả properties trừ K, ví dụ Omit<User, 'password' để không lộ mật khẩu trong response.…
Exclude<T, U loại bỏ khỏi union T những types có thể assign cho U: Exclude<'a''b''c', 'a' cho ra 'b''c'. Extract<T, U ngược lại — giữ lại những types assign được cho U: Extract<stringnumberboolean, stringnumber cho ra stringnumber. Ví dụ thực tế: type NonString<T = Exclude<T,…
ReturnType<T lấy return type của function T mà không cần khai báo lại: type Result = ReturnType<typeof fetchUser tự cập nhật khi hàm thay đổi. Awaited<T unwrap Promise đệ quy: Awaited<Promise<string cho ra string, Awaited<Promise<Promise<number cho ra number. Kết hợp cả hai cho async functions:…
NonNullable<T loại bỏ null và undefined khỏi type T: NonNullable<string null undefined cho ra string. Tương đương với Exclude<T, null undefined. Hay dùng sau khi đã kiểm tra null ở runtime nhưng TypeScript vẫn chưa tự narrow được — ví dụ kết quả từ Array.find()…
Readonly<T làm tất cả properties của T thành readonly (shallow). ReadonlyArray<T là array không thể modify (push, pop, sort không available). Dùng với as const, Redux state, functional programming. Deep readonly cần custom type: DeepReadonly<T với recursive mapped type.
Dùng mapped type iterate qua tất cả keys của T, thêm ? để optional. Hiểu cách này giúp tạo custom utility types bất kỳ.
Type guards thu hẹp type trong code branch. Loại: 1) typeof, 2) instanceof, 3) in operator, 4) equality, 5) user-defined (function với return type is Type), 6) assertion functions.
Function type với return type param is Type. Khi function return true, TS narrow type của param. Nguy hiểm: TS tin type predicate hoàn toàn, implementation sai sẽ gây runtime bug mà không có compile error.
Declaration files chứa type declarations không có implementation (ambient declarations). Dùng để type third-party libraries không viết bằng TS. @types/ packages trên npm. Tự viết .d.ts khi cần declare types cho JS code hoặc global variables.
Trong tsconfig.json, strict: true là option quan trọng nhất vì nó bật toàn bộ strict type-checking bao gồm strictNullChecks, noImplicitAny và strictFunctionTypes. target xác định phiên bản ES output (ví dụ ES2020), module chọn hệ thống module (ESNext, CommonJS), và moduleResolution quyết định cách TypeScript…
useState: useState<Type(init) khi init không đủ thông tin. useRef: useRef<HTMLInputElement(null) cho DOM refs, useRef<number(0) cho mutable values (không trigger re-render). useReducer: type actions với discriminated unions.
React.ChangeEvent<HTMLInputElement cho onChange, React.MouseEvent<HTMLButtonElement cho onClick, React.FormEvent<HTMLFormElement cho onSubmit. Nếu không nhớ chính xác: hover lên event trong IDE, hoặc dùng React.SyntheticEvent rộng hơn.
paths trong tsconfig.json map import paths để tránh relative paths dài. Cần configure cả bundler vì TS compiler chỉ handle types, không transform imports.
Cả hai mô tả được shape của object và gần như thay thế nhau được, nên chọn theo khả năng riêng của từng loại chứ không theo sở thích. Dùng interface khi: - Mô tả object/class contract mà người khác có thể mở rộng —…
Khi tắt strictNullChecks, null và undefined được coi là gán được vào mọi kiểu. Bật lên, chúng tách thành kiểu riêng, nên compiler bắt đầu báo những chỗ vốn đã có rủi ro runtime. Ba nhóm lỗi hay gặp: 1. Object is possibly 'null' —…
Trong code frontend hiện đại, union of string literal thường là lựa chọn mặc định; enum chỉ giữ khi cần một namespace giá trị thật ở runtime. Vì sao ưu tiên union: - Không sinh code runtime. enum (không phải const enum) biên dịch ra…
res.json() trả về Promise<any, và as User không kiểm tra gì ở runtime — nó chỉ nói với compiler "cứ tin tôi". Nếu backend đổi field hoặc trả về lỗi, code vẫn biên dịch sạch rồi hỏng ở nơi khác, xa điểm gây lỗi. Ba…
Dùng discriminated union thay vì một object với nhiều field optional. Union có một field chung làm discriminant (thường là status), giúp compiler biết chính xác field nào tồn tại ở mỗi nhánh. Vì sao hơn cách { isLoading, data?, error? }: cách kia cho…
TypeScript narrow theo control flow analysis. Với property có thể thay đổi (mutable), compiler chỉ giữ kết quả narrow chừng nào nó còn chắc chắn không ai ghi đè. Gọi hàm khác hoặc vào một callback chạy sau là hai điểm nó buộc phải bỏ…
Ba cách kiểm tra ở ba mức khác nhau, và quan trọng nhất là chúng giữ lại lượng thông tin kiểu khác nhau. - : Palette (annotation) — kiểm tra đúng, nhưng biến bị mở rộng về đúng kiểu khai báo. a.green.toUpperCase() lỗi vì compiler…
Vì literal widening. Khi khai báo bằng let hoặc đặt trong object literal, TypeScript mở rộng kiểu literal 'GET' thành string — do giá trị đó có thể bị gán lại. string không gán được vào union hẹp. Cách sửa: - as const cho object…
K extends keyof T là generic constraint — nó ràng buộc tham số kiểu K chỉ được là key thật của T, nhờ đó vừa chặn key sai lúc biên dịch, vừa để kiểu trả về mô tả đúng object con. Nếu bỏ constraint: -…
TypeScript widen literal về string khi T không có constraint và không đứng riêng một mình ở kiểu trả về — ví dụ hàm trả { v } hay T[]. Trả về đúng T thì literal được giữ. Muốn giữ literal trong mọi trường hợp…
Mapped type duyệt qua các key của một type để sinh type mới; mệnh đề as (TS 4.1) cho phép đổi tên key trong lúc duyệt — nhờ đó biến đổi được cả tên, không chỉ giá trị. Lọc key bằng cách remap về never…