TypeScript has become the default language for frontend and Node.js backend development at Indian product companies. Understanding TypeScript's type system deeply is now expected for senior frontend and full-stack roles. This guide covers the TypeScript interview questions you will face at Indian companies in 2026.
TypeScript type system fundamentals
TypeScript core concepts:
1. What is TypeScript? TypeScript is a statically typed superset of JavaScript. TypeScript code compiles to plain JavaScript. The type system is erased at runtime: there are no TypeScript types at runtime, only JavaScript values. TypeScript's type checker finds bugs at compile time (before you run the code).
2. Primitive types and type annotations: string, number, boolean, null, undefined, symbol, bigint. Type annotation syntax: let name: string = 'Alice'. TypeScript also infers types: const age = 25 (TypeScript infers age: number; no annotation needed).
3. interface vs type alias: Both define the shape of an object: ```ts interface User { id: number; name: string; } type User = { id: number; name: string; }; ``` Key differences: interfaces can be extended and merged (declaration merging: two interface User declarations are merged into one); type aliases can express union types, intersection types, and mapped types which interfaces cannot. Best practice: use interface for defining object shapes (especially in public APIs where declaration merging is useful); use type for union types, intersection types, and complex type transformations.
4. Union and intersection types: Union type (|): a value can be one of several types: type ID = string | number. Intersection type (&): a value must satisfy all types simultaneously: type AdminUser = User & Admin. Discriminated unions: a union where each member has a literal type field (discriminant) that narrows the type in control flow: ```ts type Shape = | { kind: 'circle'; radius: number } | { kind: 'rectangle'; width: number; height: number };
function area(shape: Shape): number { switch (shape.kind) { case 'circle': return Math.PI shape.radius 2; case 'rectangle': return shape.width shape.height; } } ```
Generics and utility types
TypeScript generics and advanced types:
1. Generics: Generics allow writing reusable code that works with multiple types while maintaining type safety: ```ts function identity<T>(value: T): T { return value; }
const name = identity<string>('Alice'); // type: string const age = identity<number>(25); // type: number ```
Generic constraints: restrict which types T can be: ```ts function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } ```
Generic interfaces and classes: ```ts interface Repository<T> { findById(id: string): Promise<T>; save(entity: T): Promise<T>; } ```
2. Built-in utility types: TypeScript includes many utility types that transform existing types: - Partial<T>: makes all properties of T optional - Required<T>: makes all properties of T required - Readonly<T>: makes all properties of T read-only - Pick<T, K>: creates a type with only the specified properties of T - Omit<T, K>: creates a type excluding the specified properties of T - Record<K, V>: creates an object type with keys K and values V - ReturnType<T>: extracts the return type of a function type - Parameters<T>: extracts the parameter types of a function type as a tuple - NonNullable<T>: removes null and undefined from T - Awaited<T>: unwraps Promise types (Awaited<Promise<string>> = string)
3. Mapped types: Transform each property of a type programmatically: ```ts type Optional<T> = { [K in keyof T]?: T[K] }; // same as Partial<T> type Nullable<T> = { [K in keyof T]: T[K] | null }; ```
TypeScript with React and Node.js
TypeScript in real projects:
1. TypeScript with React: Component props: define an interface for props and pass it as the generic parameter to React.FC: ```ts interface ButtonProps { label: string; onClick: () => void; disabled?: boolean; }
const Button: React.FC<ButtonProps> = ({ label, onClick, disabled }) => ( <button onClick={onClick} disabled={disabled}>{label}</button> ); ```
Event handlers: React's synthetic events are typed: (event: React.ChangeEvent<HTMLInputElement>) => void for onChange on input. useState: TypeScript infers the type from the initial value; use explicit type when the initial value is undefined or null: const [user, setUser] = useState<User | null>(null).
useRef: useRef<HTMLInputElement>(null) for a ref to a DOM element; useRef<number>(0) for a mutable value.
2. TypeScript with Express (Node.js): Install @types/express for type declarations. Typed request: use generics on Request to type the body and params: ```ts app.post('/users', (req: Request<{}, {}, CreateUserDto>, res: Response) => { const { name, email } = req.body; // TypeScript knows these are from CreateUserDto }); ```
3. tsconfig.json key settings: - strict: true: enables all strict type checks (strictNullChecks, noImplicitAny, strictFunctionTypes, etc.) - strictNullChecks: true: null and undefined are not assignable to other types; prevents null pointer exceptions - noImplicitAny: true: error when TypeScript infers any - target: sets the JavaScript version to compile to - moduleResolution: node (CommonJS) or bundler (for Vite/Webpack) - paths: configure module aliases (@ for src/)
Practise TypeScript interview questions with HireStepX's AI voice interviewer. Get scored feedback on your explanations of generics, utility types, and TypeScript with React. First 2 sessions free.
Practice freeTypeScript type narrowing and advanced patterns
TypeScript advanced features:
1. Type narrowing: TypeScript narrows the type of a variable within a conditional block based on type guards: - typeof: typeof x === 'string' narrows x to string - instanceof: err instanceof Error narrows err to Error - in: 'name' in obj narrows obj to types that have a 'name' property - Discriminated union switch: see the Shape example above
2. Custom type guards: A function with a return type of 'value is Type' teaches TypeScript about the narrowing: ```ts function isUser(value: unknown): value is User { return typeof value === 'object' && value !== null && 'id' in value; }
if (isUser(data)) { console.log(data.id); // TypeScript knows data is User here } ```
3. Declaration files (.d.ts): Declaration files describe the types of JavaScript code without providing implementation. When to write one: you are consuming a JavaScript library that has no TypeScript types (@types/ package doesn't exist); you are authoring a JavaScript library that others consume from TypeScript.
4. Template literal types: TypeScript can perform string manipulation at the type level: ```ts type EventName = 'click' | 'focus' | 'blur'; type Handler = `on${Capitalize<EventName>}`; // 'onClick' | 'onFocus' | 'onBlur' ```
5. Conditional types: Type-level if/else: ```ts type IsArray<T> = T extends any[] ? true : false; type A = IsArray<string[]>; // true type B = IsArray<string>; // false ```
6. The infer keyword: Extract type parameters from other types inside conditional types: ```ts type UnpackPromise<T> = T extends Promise<infer U> ? U : T; type Resolved = UnpackPromise<Promise<string>>; // string ```
Frequently asked questions
Explore more