Interview Prep
Interview Questions on TypeScript — Types, Generics, Interfaces, and What Frontend Interviews Actually Test
TypeScript has become the default for frontend and full-stack roles in India. React, Angular, and Node.js projects all use TypeScript now. If you are interviewing for any JavaScript-adjacent role, TypeScript questions are guaranteed. Here is what they ask.

TypeScript is now the industry standard for any serious JavaScript project. Every frontend and full-stack interview tests it.
TypeScript in Indian IT Interviews
TypeScript has gone from optional to mandatory in the Indian job market. Product companies like Flipkart, Razorpay, Swiggy, and Zerodha use TypeScript across their frontend and backend codebases. Even service companies working on Angular or React projects now require TypeScript knowledge. If a job description mentions React, Angular, or Node.js — TypeScript is implied.
TypeScript interviews test whether you understand the type system beyond basic annotations. Interviewers ask about generics, utility types, type narrowing, and how TypeScript compiles to JavaScript. This guide covers the actual questions asked in Indian interviews.
TypeScript interviews are not about memorizing types. They are about understanding WHY types exist and how they prevent bugs that JavaScript cannot catch.
TypeScript Basics
Q1: What is TypeScript? How is it different from JavaScript?
TypeScript = JavaScript + static type system
Key differences:
JavaScript TypeScript
───────────────────── ─────────────────────
Dynamic typing Static typing
Errors at runtime Errors at compile time
No type annotations Type annotations
Runs directly in browser Compiles to JavaScript
.js extension .ts / .tsx extension
// JavaScript — error at RUNTIME
function add(a, b) {
return a + b;
}
add("5", 3); // "53" — no error, wrong result
// TypeScript — error at COMPILE TIME
function add(a: number, b: number): number {
return a + b;
}
add("5", 3); // Error: Argument of type 'string'
// is not assignable to parameter of type 'number'
// TypeScript compiles to JavaScript:
// tsc app.ts → app.js
// The browser never sees TypeScript — only JavaScriptQ2: What are the basic types in TypeScript?
// Primitive types
let name: string = "Rahul";
let age: number = 25;
let isActive: boolean = true;
let data: null = null;
let value: undefined = undefined;
// Arrays
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["a", "b", "c"];
// Tuple — fixed-length array with specific types
let user: [string, number] = ["Rahul", 25];
// Enum
enum Status { Active, Inactive, Pending }
let s: Status = Status.Active; // 0
// Any — opt out of type checking (avoid!)
let anything: any = "hello";
anything = 42; // no error — defeats the purpose
// Unknown — safer alternative to any
let input: unknown = "hello";
// input.toUpperCase(); // Error! Must narrow first
if (typeof input === "string") {
input.toUpperCase(); // OK after type check
}
// Void — function returns nothing
function log(msg: string): void {
console.log(msg);
}
// Never — function never returns (throws or infinite loop)
function throwError(msg: string): never {
throw new Error(msg);
}Interfaces and Type Aliases
Q3: What is the difference between interface and type?
// Interface — describes object shape
interface User {
name: string;
age: number;
email?: string; // optional
readonly id: number; // cannot be changed
}
// Type alias — can describe any type
type User = {
name: string;
age: number;
};
type ID = string | number; // union — interface cannot do this
type Pair = [string, number]; // tuple
// Key differences:
// 1. Interface can be extended (declaration merging)
interface Animal { name: string; }
interface Animal { sound: string; } // merged!
// Animal now has both name and sound
// Type cannot be merged
type Animal = { name: string; };
// type Animal = { sound: string; }; // Error! Duplicate
// 2. Interface uses 'extends', type uses '&'
interface Dog extends Animal { breed: string; }
type Dog = Animal & { breed: string; };
// 3. Type can represent unions, tuples, primitives
type Status = "active" | "inactive"; // interface cannot
// When to use which:
// Interface → object shapes, class contracts, APIs
// Type → unions, tuples, complex types, utility typesQ4: What are union and intersection types?
// Union (|) — value can be ONE of several types
type ID = string | number;
let userId: ID = "abc123";
userId = 42; // also valid
// Discriminated union (powerful pattern):
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;
}
}
// Intersection (&) — value must satisfy ALL types
type HasName = { name: string };
type HasAge = { age: number };
type Person = HasName & HasAge;
// Person must have BOTH name and age
const p: Person = { name: "Priya", age: 25 }; // OK
// const p: Person = { name: "Priya" }; // Error: missing ageGenerics
Generics are the most tested advanced TypeScript topic. They let you write reusable, type-safe code without using ‘any’. If you understand generics, you understand TypeScript at a senior level.
Q5: What are generics? Why use them?
// Without generics — loses type information
function identity(arg: any): any {
return arg;
}
const result = identity("hello"); // type is 'any' — useless
// With generics — preserves type information
function identity<T>(arg: T): T {
return arg;
}
const result = identity("hello"); // type is 'string'
const num = identity(42); // type is 'number'
// Generic interface
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
const userResponse: ApiResponse<User> = {
data: { name: "Rahul", age: 25 },
status: 200,
message: "Success"
};
// Generic with constraints
function getLength<T extends { length: number }>(arg: T): number {
return arg.length;
}
getLength("hello"); // OK — string has length
getLength([1, 2, 3]); // OK — array has length
// getLength(42); // Error — number has no length
// Generic with keyof
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "Priya", age: 25 };
getProperty(user, "name"); // returns string
// getProperty(user, "email"); // Error: "email" not in User
Generics are what separate TypeScript beginners from advanced users. Every senior interview tests them.
Utility Types and Advanced Patterns
Q6: What are the most important utility types?
interface User {
name: string;
age: number;
email: string;
}
// Partial<T> — all properties optional
type UpdateUser = Partial<User>;
// { name?: string; age?: number; email?: string; }
// Required<T> — all properties required
type StrictUser = Required<User>;
// Pick<T, K> — select specific properties
type UserName = Pick<User, "name" | "email">;
// { name: string; email: string; }
// Omit<T, K> — exclude specific properties
type UserWithoutEmail = Omit<User, "email">;
// { name: string; age: number; }
// Readonly<T> — all properties readonly
type FrozenUser = Readonly<User>;
// Cannot modify any property
// Record<K, V> — create object type with specific keys
type Roles = Record<"admin" | "user" | "guest", boolean>;
// { admin: boolean; user: boolean; guest: boolean; }
// ReturnType<T> — extract return type of a function
function getUser() { return { name: "Rahul", age: 25 }; }
type UserType = ReturnType<typeof getUser>;
// { name: string; age: number; }
// These utility types are asked in 60%+ of TS interviewsQ7: What is type narrowing? How does TypeScript narrow types?
// Type narrowing = refining a broad type to a specific one
function process(input: string | number) {
// input is string | number here
if (typeof input === "string") {
// TypeScript KNOWS input is string here
console.log(input.toUpperCase()); // OK
} else {
// TypeScript KNOWS input is number here
console.log(input.toFixed(2)); // OK
}
}
// Narrowing techniques:
// 1. typeof guard
if (typeof x === "string") { /* x is string */ }
// 2. instanceof guard
if (x instanceof Date) { /* x is Date */ }
// 3. in operator
if ("name" in obj) { /* obj has name property */ }
// 4. Discriminated unions (most powerful)
type Cat = { kind: "cat"; meow(): void };
type Dog = { kind: "dog"; bark(): void };
type Pet = Cat | Dog;
function handle(pet: Pet) {
if (pet.kind === "cat") {
pet.meow(); // TypeScript knows it's Cat
}
}
// 5. Custom type guard
function isString(x: unknown): x is string {
return typeof x === "string";
}Q8: What is the difference between ‘any’, ‘unknown’, and ‘never’?
// any — disables type checking entirely
let a: any = "hello";
a.foo.bar.baz; // no error — TypeScript gives up
// Use: migration from JS, third-party libs without types
// unknown — type-safe version of any
let b: unknown = "hello";
// b.toUpperCase(); // Error! Must narrow first
if (typeof b === "string") {
b.toUpperCase(); // OK after narrowing
}
// Use: when you don't know the type but want safety
// never — impossible type (no value can be never)
function fail(msg: string): never {
throw new Error(msg); // never returns
}
// Also used for exhaustive checks:
type Shape = "circle" | "square";
function area(s: Shape) {
switch (s) {
case "circle": return /* ... */;
case "square": return /* ... */;
default:
const _exhaustive: never = s; // Error if new shape added
return _exhaustive;
}
}
// Rule: avoid 'any', prefer 'unknown' when type is uncertainHow to Prepare
TypeScript Interview — Priority by Experience
Junior (0-2 years)
- • Basic types & annotations
- • Interface vs type
- • Union & intersection
- • any vs unknown
- • Enums
Mid (2-4 years)
- • Generics
- • Utility types
- • Type narrowing
- • Discriminated unions
- • Type guards
Senior (5+ years)
- • Conditional types
- • Mapped types
- • Template literal types
- • Module augmentation
- • tsconfig optimization