TypeScript Interview Questions — Comprehensive (100+)
A concise, practical collection of TypeScript interview questions and short answers with code examples.
1. What is TypeScript and why use it?
TypeScript is a strongly typed superset of JavaScript that adds optional static types, interfaces, and
advanced tooling. Use it for earlier error detection, better refactoring, and improved IDE support.
2. How does TypeScript differ from JavaScript?
TS adds static types, compile-time checks, and language features (enums, interfaces, generics). It
compiles to plain JS that runs anywhere JS runs.
3. What are Type Annotations?
Explicitly declare variable types: let x: number = 5;. They help the compiler catch type errors early.
4. What are Interfaces?
Interfaces define shapes of objects and enforce structure: interface User { id: number; name: string }. They
support optional/readonly properties.
5. What is the difference between type and interface?
type can create aliases (including unions, tuples); interface is extendable/mergeable. Interfaces support
declaration merging; types are more flexible with unions.
6. Explain Union and Intersection types.
Union (A | B) is either A or B. Intersection (A & B) combines A and B properties.
7. What are Generics?
Generics create reusable components with type parameters: function id(x: T): T { return x } ensures input
and output types match.
8. How do you constrain generics?
Use extends: function fn(x:T){} to require certain properties.
9. What is type inference?
TS infers types when you don't annotate: let x = 3; // inferred number. Inference reduces verbosity.
10. What is type assertion?
Tell the compiler a value's type: const el = document.getElementById('id') as HTMLDivElement;. Use
carefully — overrides checks.
11. What are enums?
Enums define named constants: enum Color {Red, Green, Blue}. There are numeric and string enums.
12. When should you use enums vs union types?
Use enums for named constants and easier runtime presence. For purely type-level sets, union string literal
types are lighter: type Color = 'red'|'green'.
13. What are Literal Types?
Types fixed to specific values: type T = 'a' | 'b' | 5;. Useful for configuration and discriminated unions.
14. Explain Discriminated Unions.
Use a common literal property to narrow types: type A = {kind:'a', x:number} etc. Switch on kind to get safe
narrowing.
15. What are Type Guards?
Functions or checks that narrow types at runtime: if (typeof x === 'string') {...} or custom guards: function
isFoo(x:any): x is Foo { return x && x.type==='foo' }.
16. How to narrow types with instanceof and in?
instanceof checks constructor at runtime; in checks property presence to narrow union members.
17. What are Utility Types? Name common ones.
Built-in helpers: Partial, Required, Pick, Omit, Record, Readonly, ReturnType, Parameters.
18. What is mapped types?
Create new types by mapping properties: type Nullable = { [P in keyof T]: T[P] | null }. Many utility types are
mapped types.
19. How to create a readonly array or tuple?
Use readonly: const arr: readonly number[] = [1,2]; or readonly [number, string]. Prevents mutation
methods.
20. What is the difference between 'unknown' and 'any'?
any disables type checking; unknown is safer — you must narrow before using it.
21. Why prefer 'unknown' over 'any'?
Unknown forces explicit checks, reducing runtime errors while keeping flexibility.
22. What is 'never' type?
never is for values that never occur (e.g., function that always throws or exhaustive switch default
unreachable).
23. Explain Declaration Files (.d.ts).
Provide type info for JS libs. Either shipped with packages or created via declare module or DefinitelyTyped
(@types/*).
24. What is 'tsconfig.json'?
Project configuration file controlling compiler options, include/exclude paths, module target, strictness, etc.
25. Name important tsconfig compiler options.
target, module, strict, noImplicitAny, strictNullChecks, esModuleInterop, skipLibCheck, moduleResolution.
26. What does 'strict' do?
Enables multiple strict checks (including noImplicitAny, strictNullChecks, strictFunctionTypes, etc.). It's
recommended for safety.
27. Explain 'strictNullChecks'.
When true, null/undefined are not assignable to other types unless explicitly allowed (e.g., string | null).
28. How to handle optional properties?
Use ?: name?: string means property may be undefined. Combine with Partial for many optional props.
29. What are Index Signatures?
Allow dynamic property names: interface Dict { [key:string]: number }. Use for maps/objects with unknown
keys.
30. What is 'module' vs 'namespace'?
Modern TS uses ES modules (import/export). Namespaces are legacy internal modules; modules are
recommended.
31. What are Ambient Declarations?
Use declare to describe external variables/types, e.g., declare const MY_GLOBAL: string; or declare
module for JS libs.
32. How to export and import types only?
Use import type { T } from './a' and export type { T } to avoid runtime imports (Type-only imports).
33. Explain 'type compatibility' (structural typing).
TS uses structural type system — types are compatible by shape, not name. If shapes match, assignment
works.
34. What is 'excess property checking'?
When assigning object literals to typed variables, TS checks for unexpected properties to catch typos.
35. What are Generics in Classes?
Classes can be generic: class Box{ value: T }. Allows container types to be reusable.
36. Describe keyof and typeof type operators.
keyof T yields property names union. typeof x in types captures runtime variable type for reuse.
37. How to type a function that returns another function?
Use function types or generics: function makeAdder(n:number): (x:number)=>number { return x=>x+n }.
38. How to type callbacks properly?
Define parameter and return types: type Mapper= (item:T,index:number)=>U; then arr.map(mapper).
39. Explain 'this' types in functions and classes.
Use this: Type in function signatures to type this context. E.g., function f(this: HTMLElement){} or class A{
method(this: A){} }.
40. What are Conditional Types?
Types that depend on a condition: type IsString = T extends string ? true : false. Powerful for
transformations.
41. What is distributive conditional types?
When conditional types distribute over unions: T extends U ? X : Y acts on each union member unless
wrapped in tuple.
42. How to prevent distributive behavior?
Wrap T in a tuple: [T] extends [U] ? X : Y to stop distribution.
43. What are template literal types?
Build string unions: type Event = on${Capitalize}; Useful for typed keys like onClick etc.
44. How to enforce immutability types?
Use Readonly, ReadonlyArray, and as const for literal immutability inference.
45. What does 'as const' do?
Makes an object/array deeply readonly and infers literal types instead of widening to string/number.
46. How to type overloaded functions?
Write multiple function signatures above the implementation; only one implementation with general types.
47. What are function overload pitfalls?
Implementation signature must be compatible and not visible externally; return types must be handled with
narrowing.
48. Explain structural vs nominal typing.
TS is structural. Nominal typing would require name-based matching; not native in TS (can be simulated).
49. How to simulate nominal types?
Use branding: type ID = string & {__brand:'id'} to differentiate without runtime cost.
50. How to type REST API responses?
Define interfaces/types for responses and use generics in fetch wrappers: async function get(url):
Promise{}.
51. How to type Redux actions and reducers?
Use discriminated unions for actions and ReturnType for action types; use generics for state.
52. How to type event handlers in DOM/React?
Use built-in types: React.MouseEvent or MouseEvent for DOM. For React use import React from 'react'.
53. How to type React components (FC vs plain function)?
React.FC adds children prop by default; many prefer plain (props: Props) => JSX.Element to avoid implicit
children.
54. How to type higher-order components (HOC)?
Use generics and conditional types to preserve wrapped component props and remove injected props
using Omit/Exclude.
55. How to type ref forwarding in React?
Use React.forwardRef((props, ref) => ...) and Ref types to annotate forwarded ref type.
56. How to type styled-components or CSS-in-JS theme?
Define DefaultTheme interface and augment styled-components module, or pass theme generic to styled
helper.
57. What are declaration merging rules?
Interfaces can merge across declarations; functions and namespaces can also merge with compatible
shapes.
58. How to write a custom type guard?
Return x is T and perform runtime checks: function isNumber(x:any): x is number { return typeof
x==='number' }.
59. How to type JSON.parse safely?
JSON.parse returns any. Use generics with runtime validation or zod/io-ts schemas to validate shape:
const data = JSON.parse(s) as MyType (unsafe without validation).
60. What are Template literal types with unions?
Combine unions with template literals to create variations, e.g., type Size = 'S'|'M'; type Key =
${Size}-price;.
61. How to use 'infer' in conditional types?
Extract subtypes: type Return = T extends (...args:any)=>infer R ? R : never gets function return type.
62. How to type tuple operations?
Tuples can be typed precisely: type T = [number,string]; and you can use variadic tuple types in newer TS
versions.
63. What are Variadic Tuple Types?
Allow spreading tuple types in generics: type Prepend = [E, ...T]. Useful for function args transformations.
64. How to type 'PartialDeep' or deep mapped types?
Use recursive mapped types: type DeepPartial = { [P in keyof T]?: DeepPartial } (careful with circular refs).
65. How to achieve conditional property requirement?
Combine mapped and conditional types to make properties required/optional based on other properties
(advanced patterns).
66. What is 'lib' option in tsconfig?
Specifies built-in lib typings (DOM, ES2019, DOM.Iterable, WebWorker). Match to target and environment.
67. How to handle third-party JS without types?
Install @types/lib if available, write minimal .d.ts with required declarations, or use declare module 'lib'
temporarily.
68. How to write type-safe builders/fluent APIs?
Use generics and this typing or return new typed instances; e.g., class Builder{ with(k:K,v:T[K]){...} }.
69. How to type currying functions?
Use overloads or variadic tuple types to preserve argument types and return types across partial
application.
70. How to work with mixed JS and TS codebases?
Use allowJs, incremental adoption, declare types for critical modules, and enable skipLibCheck to reduce
friction.
71. How to configure path aliases?
Use compilerOptions.paths and baseUrl in tsconfig, and configure bundler (webpack/tsconfig-paths) and
ts-node accordingly.
72. How to type plugin/extension systems?
Use generics with registration maps, mapped types keyed by plugin names, and index signatures for
dynamic lookups.
73. How to type errors and exceptions?
By default catch is unknown in useUnknownInCatchVariables. Narrow before using: if (err instanceof Error)
{ err.message }.
74. How to type optional chaining and nullish coalescing?
Use ?. and ?? operators; TS types reflect possible undefined values when strictNullChecks is on.
75. How to create strongly typed enums alternative?
Use union of literal types or const objects with as const to get both type and runtime value without enum
quirks.
76. What are pitfalls of structural typing with classes?
Private/protected members affect compatibility; two classes with same public shape but different private
members are incompatible.
77. How to write tests for type-level code?
Use tsd or dtslint to assert types, or compile-time checks via sample code in test suite to ensure typings
behave as expected.
78. How to keep types in sync with runtime code?
Prefer single-source constructs (e.g., as const objects) or generate types from schemas (zod -> TypeScript
types).
79. How to use JSDoc with TypeScript?
TS can infer types from JSDoc in JS files; use // @ts-check and JSDoc annotations for gradual typing.
80. How to handle circular type references?
Use interfaces and type carefully; sometimes break cycles by using any or indirection via functions to avoid
infinite recursion in mapped types.
81. How to improve compile times?
Enable incremental, skipLibCheck, esbuild/SWC for faster builds, use project references, and limit include
globs.
82. What are project references?
Split large codebase into smaller tsconfig projects with references for faster builds and better incremental
compilation.
83. How to migrate from JavaScript to TypeScript?
Start with allowJs and checkJs, add --noImplicitAny gradually, convert modules one by one and add
declaration files as needed.
84. How to type plugin systems with unknown keys?
Use Record or mapped types over keyof typeof plugins when plugin names are known at compile time.
85. How to use satisfies operator (TS 4.9+)?
const x = {...} as const satisfies MyType; ensures x satisfies type without widening or changing inferred
literal types.
86. How to type JSON schemas to TypeScript types?
Use codegen tools (quicktype, json-schema-to-typescript) or runtime validators that export types (zod,
io-ts).
87. How to debug complex types?
Use type simplification, helper debug types, and IDE peek to inspect inferred types; break big types into
named pieces.
88. How to handle optional tuple elements?
Type as [number, string?] and use runtime checks; variadic tuples improved flexibility.
89. What is emitDecoratorMetadata and decorator caveats?
Emits runtime type metadata for decorators (experimental). Use carefully; metadata often limited
(design:type shows constructor only).
90. How to type metadata-driven libraries?
Combine decorators with generics and explicit type annotations to keep types safe; avoid relying solely on
runtime metadata.
91. How to prevent accidental any?
Enable noImplicitAny and strict mode, and avoid suppressing errors with any or // @ts-ignore.
92. How to use moduleResolution option?
Controls algorithm (node/classic). Use node for Node.js style resolution, configure baseUrl and paths as
needed.
93. How to type websocket/message payloads?
Define discriminated unions for message types and use a runtime parser/validator to guarantee safety at
runtime.
94. How to use the TypeScript compiler API?
The compiler API can parse and analyze code (ts.createProgram, typeChecker). Useful for linters/codegen
but has steep learning curve.
95. How to write declaration files for a library?
Author .d.ts describing public surface, include them via types field in package.json or ship alongside
compiled JS.
96. How to handle different lib targets (DOM vs Node)?
Use lib in tsconfig to include appropriate globals or split configs for node/browser builds.
97. How to type a function with overloads and generics together?
List overload signatures (narrow) then implement one general function body; use generics in signatures as
needed.
98. How to ensure API clients are type-safe?
Use generated types from OpenAPI/GraphQL schemas or write precise types and validate responses at
runtime with schema validators.
99. How to use inference from tuple/array operations?
Newer TS versions infer tuple spreads and can preserve const contexts when as const is used.
100. How to handle edge cases with extends and primitive wrappers?
Be careful comparing string vs String (object). Prefer primitives in types and avoid wrapper objects.
101. Example: Type-safe fetch wrapper (short)
async function getJSON(url:string):Promise{ const r=await fetch(url); return r.json() as Promise; } (Add
runtime validation for safety).
102. Example: Generic utility type - Mutable
type Mutable = { -readonly [P in keyof T]: T[P] } removes readonly modifiers.
103. Example: Discriminated union narrow
type A = {kind:'a', x:number}; type B={kind:'b', y:string}; function f(v:A|B){ if(v.kind==='a') return v.x; else
return v.y }
104. Tips for interviews
Explain trade-offs, prefer safety (strict), show knowledge of tooling (tsconfig, build), mention runtime
validation and testing types.
Good luck with your interviews! Practice explaining answers and typing small code snippets by hand.
Generated by ChatGPT — Comprehensive TypeScript Q&A; (100+).