TypeScript Interview Questions

These TypeScript interview questions cover language fundamentals, the type system, generics, utility types, compiler configuration, modules, asynchronous code, and practical design decisions commonly discussed in frontend, Node.js, and automation-testing interviews. Each answer explains the concept and the reasoning an interviewer may expect.

Core TypeScript Interview Questions for Freshers

1. What is TypeScript?

TypeScript is a statically typed language built on JavaScript. It adds a compile-time type system and related tooling while preserving JavaScript syntax and runtime behavior. TypeScript source code is checked and transformed into JavaScript that can run in browsers, Node.js, and other JavaScript environments.

2. How is TypeScript different from JavaScript?

JavaScript is dynamically typed, so many type errors appear only when the program runs. TypeScript can detect incompatible assignments, invalid property access, missing arguments, and similar issues before execution. TypeScript also supports interfaces, type aliases, generics, utility types, and compiler options that do not exist as runtime JavaScript features.

3. Does TypeScript run directly in a browser?

No. Browsers execute JavaScript rather than TypeScript source files. A TypeScript compiler or build tool converts TypeScript into JavaScript. Type annotations and most other type-system constructs are erased during compilation.

4. What is type inference in TypeScript?

Type inference is the compiler’s ability to determine a type from the surrounding code without an explicit annotation. In the following example, TypeScript infers count as number and rejects a later string assignment.

</>
Copy
let count = 10;
// count = "ten"; // Error: Type 'string' is not assignable to type 'number'

5. What are union and intersection types?

A union type allows a value to be one of several types. An intersection type combines multiple types into one type that must satisfy all members.

</>
Copy
type Identifier = string | number;

type Timestamped = {
  createdAt: Date;
};

type User = {
  id: Identifier;
  name: string;
};

type StoredUser = User & Timestamped;

6. What is the difference between any and unknown?

any disables most type checking for a value. unknown can receive any value, but it must be narrowed or asserted before properties or methods are used. Use unknown when input is not yet trusted, such as parsed data, caught errors, or external API responses.

</>
Copy
function printValue(value: unknown): void {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  }
}

7. What are void and never?

void commonly describes a function whose return value is not used. never represents a value that cannot occur. A function that always throws or never finishes can return never. The type is also useful for exhaustive checks.

</>
Copy
function logMessage(message: string): void {
  console.log(message);
}

function fail(message: string): never {
  throw new Error(message);
}

8. What is the difference between null and undefined?

undefined usually means that a value has not been assigned or a property is absent. null is commonly used as an intentional empty value. With strictNullChecks enabled, neither value is assignable to an unrelated type unless it is included explicitly in that type.

TypeScript Interfaces, Type Aliases, and Object Modeling

9. What is the difference between an interface and a type alias?

Both can describe object shapes. Interfaces support declaration merging and are commonly used for public object contracts. Type aliases can name unions, intersections, tuples, primitives, conditional types, mapped types, and object shapes. For ordinary object models, either may be appropriate; consistency and the need for declaration merging usually guide the choice.

</>
Copy
interface Account {
  id: number;
  name: string;
}

type AccountStatus = "active" | "disabled";

type AccountRecord = Account & {
  status: AccountStatus;
};

10. What is declaration merging?

Declaration merging occurs when compatible declarations with the same name are combined. Interfaces are a common example. This is useful when augmenting library or global declarations, but it should be used carefully because declarations can be spread across files.

</>
Copy
interface Settings {
  theme: string;
}

interface Settings {
  language: string;
}

const settings: Settings = {
  theme: "dark",
  language: "en"
};

11. What do optional and readonly properties mean?

An optional property marked with ? may be absent. A readonly property cannot be reassigned through that type after initialization. readonly is a compile-time restriction; it does not automatically freeze the JavaScript object at runtime.

</>
Copy
interface Product {
  readonly id: number;
  name: string;
  description?: string;
}

12. What is structural typing in TypeScript?

TypeScript checks whether a value has the required structure rather than requiring an explicit declaration that one named type implements another. A value with at least the required compatible members can usually be assigned to that type.

</>
Copy
interface Named {
  name: string;
}

const employee = {
  name: "Asha",
  department: "Engineering"
};

const named: Named = employee;

13. What is excess property checking?

When an object literal is assigned directly to a target type, TypeScript checks for unexpected properties more strictly. This catches likely spelling mistakes or incorrect fields. The rule is not identical to exact-object typing because values stored in variables are primarily checked for whether they contain the required structure.

Type Narrowing and Type Safety Interview Questions

14. What is type narrowing?

Type narrowing reduces a broad type to a more specific type based on runtime checks that TypeScript understands. Common narrowing tools include typeof, instanceof, equality checks, the in operator, truthiness checks, and discriminated unions.

</>
Copy
function format(value: string | number): string {
  if (typeof value === "number") {
    return value.toFixed(2);
  }

  return value.trim();
}

15. What is a user-defined type guard?

A user-defined type guard is a function whose return type uses a type predicate such as value is User. It tells the compiler how a successful runtime check narrows the input.

</>
Copy
interface User {
  id: number;
  name: string;
}

function isUser(value: unknown): value is User {
  if (typeof value !== "object" || value === null) {
    return false;
  }

  const candidate = value as Record<string, unknown>;

  return typeof candidate.id === "number"
    && typeof candidate.name === "string";
}

16. What is a discriminated union?

A discriminated union is a union whose members share a literal-valued property, often named type, kind, or status. Checking that property narrows the value to the corresponding member.

</>
Copy
type Result =
  | { status: "success"; data: string }
  | { status: "error"; message: string };

function describe(result: Result): string {
  if (result.status === "success") {
    return result.data;
  }

  return result.message;
}

17. How do you perform an exhaustive check with never?

After all members of a discriminated union have been handled, the remaining value should have type never. Assigning it to a never variable makes the compiler report an error when a new union member is added but not handled.

</>
Copy
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.side ** 2;
    default: {
      const exhaustiveCheck: never = shape;
      return exhaustiveCheck;
    }
  }
}

18. What is a type assertion, and how is it different from runtime conversion?

A type assertion tells the compiler to treat a value as a specified type. It does not validate, parse, clone, or convert the value at runtime. Runtime conversion requires JavaScript logic such as Number(value), String(value), or a validation function.

19. What do optional chaining and nullish coalescing do?

Optional chaining, written as ?., stops property access or a call when the value is null or undefined. Nullish coalescing, written as ??, supplies a fallback only for null or undefined, unlike ||, which also treats values such as 0, an empty string, and false as falsy.

TypeScript Generics and Utility Types Interview Questions

20. What are generics in TypeScript?

Generics let code preserve relationships between input and output types without replacing them with any. A type parameter acts as a placeholder that is inferred or supplied when the generic is used.

</>
Copy
function first<T>(items: T[]): T | undefined {
  return items[0];
}

const firstNumber = first([10, 20, 30]);
const firstName = first(["Asha", "Ravi"]);

21. How do generic constraints work?

A generic constraint limits the types accepted by a type parameter. It allows the generic implementation to use members guaranteed by the constraint.

</>
Copy
function getLength<T extends { length: number }>(value: T): number {
  return value.length;
}

getLength("TypeScript");
getLength([1, 2, 3]);

22. What does keyof do?

keyof produces a union of known property keys for a type. It is often combined with generics and indexed access types to create type-safe property utilities.

</>
Copy
function getProperty<T, K extends keyof T>(object: T, key: K): T[K] {
  return object[key];
}

const user = { id: 1, name: "Asha" };
const name = getProperty(user, "name");

23. What are mapped types?

A mapped type creates a new type by iterating over the keys of another type. It can preserve, add, or remove modifiers such as optional and readonly.

</>
Copy
type Optional<T> = {
  [K in keyof T]?: T[K];
};

interface Profile {
  name: string;
  age: number;
}

type ProfileUpdate = Optional<Profile>;

24. What are conditional types?

A conditional type selects one type or another based on an assignability test. Its general form is T extends U ? X : Y. Conditional types are used in many standard utility types and can distribute over unions when the checked type is a generic type parameter.

</>
Copy
type IsString<T> = T extends string ? true : false;

25. What does infer mean in a conditional type?

infer introduces a type variable inside the matching branch of a conditional type. It is commonly used to extract a function return type, array element type, or resolved promise value.

</>
Copy
type ElementType<T> = T extends Array<infer U> ? U : T;

type NumberItem = ElementType<number[]>;
type TextItem = ElementType<string>;

26. Which built-in utility types should a TypeScript developer know?

Frequently used utility types include Partial<T>, Required<T>, Readonly<T>, Pick<T, K>, Omit<T, K>, Record<K, T>, Exclude<T, U>, Extract<T, U>, NonNullable<T>, Parameters<T>, ReturnType<T>, and Awaited<T>.

</>
Copy
interface Customer {
  id: number;
  name: string;
  email: string;
}

type CustomerSummary = Pick<Customer, "id" | "name">;
type CustomerInput = Omit<Customer, "id">;
type CustomerPatch = Partial<CustomerInput>;

27. What is the satisfies operator?

The satisfies operator checks that an expression is assignable to a target type without replacing the expression’s more specific inferred type. It is useful for validating configuration objects while retaining literal or property-level information.

</>
Copy
type RouteName = "home" | "profile";

const routes = {
  home: "/",
  profile: "/profile"
} satisfies Record<RouteName, string>;

28. What does as const do?

A const assertion prevents literal widening, marks object properties as readonly, and turns array literals into readonly tuples. It is useful when exact literal values are needed for discriminated unions or configuration data.

</>
Copy
const request = {
  method: "GET",
  path: "/users"
} as const;

TypeScript Classes and Object-Oriented Design Questions

29. What access modifiers are available in TypeScript?

public members are accessible wherever the instance is accessible. protected members are available inside the class and subclasses. private members are restricted to the declaring class by TypeScript. JavaScript private fields written with # provide runtime-enforced privacy and have different semantics from the TypeScript private keyword.

30. What is the difference between an abstract class and an interface?

An interface describes a type contract and does not provide runtime implementation. An abstract class can define fields, implemented methods, constructors, protected members, and abstract members that subclasses must implement. A class can implement multiple interfaces but extend only one base class.

31. What are parameter properties?

Parameter properties create and initialize class members directly from constructor parameters by adding an access modifier or readonly.

</>
Copy
class Employee {
  constructor(
    public readonly id: number,
    private salary: number
  ) {}
}

32. What is the difference between implements and extends?

A class uses extends to inherit implementation and instance behavior from a base class. It uses implements to prove that its instance shape satisfies an interface or another compatible type contract. Implementing a type does not copy method bodies into the class.

TypeScript Compiler, Modules, and Project Configuration Questions

33. What is tsconfig.json?

tsconfig.json defines the root of a TypeScript project and configures compiler behavior. Common settings include the language target, module system, module resolution, output directory, source maps, declaration output, interoperability options, strictness checks, and the files included or excluded from compilation.

</>
Copy
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "outDir": "dist"
  },
  "include": ["src/**/*.ts"]
}

34. What does the strict compiler option enable?

strict enables a family of stricter type-checking options. Important checks include implicit any detection, strict handling of null and undefined, stricter function types, property initialization checks, and safer handling of this. Individual checks can still be configured separately.

35. What is the difference between target, module, and moduleResolution?

target controls the JavaScript language level emitted by the compiler. module controls how module syntax is emitted or modeled. moduleResolution controls how import specifiers are matched to source files, packages, and declaration files. These options should be selected together based on the actual runtime and build tool.

36. What are declaration files?

Declaration files use the .d.ts extension to describe the types of JavaScript code without providing its runtime implementation. They can describe a package, global variables, module augmentation, or the public API generated from a TypeScript library.

37. What are ambient declarations?

Ambient declarations describe values that exist elsewhere at runtime. They commonly use declare and appear in declaration files. An ambient declaration tells TypeScript about a value but does not create that value in emitted JavaScript.

38. What is the difference between namespaces and ES modules?

ES modules use import and export and are the standard choice for modern applications and libraries. TypeScript namespaces group declarations in the global scope and were more common before broad ES module adoption. New modular code generally uses ES modules unless it must integrate with a specific global-script environment.

39. What are source maps?

Source maps connect generated JavaScript back to the original TypeScript source. They allow browser and Node.js debugging tools to show TypeScript file names and line numbers while the emitted JavaScript is running.

Experienced TypeScript Developer Interview Questions

40. Does TypeScript provide runtime validation?

No. TypeScript checks code during development or compilation, but its types are normally erased. Data received from HTTP requests, storage, command-line arguments, environment variables, or other external sources must still be validated at runtime before it is trusted.

41. How should an API response be handled safely?

Treat the response as unknown, validate its shape at the application boundary, and only then expose a typed value to the rest of the program. Avoid writing response.json() as User as the only safety measure because a type assertion performs no runtime check.

</>
Copy
async function loadUser(id: number): Promise<User> {
  const response = await fetch(`/api/users/${id}`);

  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }

  const data: unknown = await response.json();

  if (!isUser(data)) {
    throw new Error("Invalid user response");
  }

  return data;
}

42. What is function overload resolution in TypeScript?

Function overloads expose multiple call signatures followed by one implementation signature. Callers are checked against the overload signatures, while the implementation must safely handle all supported forms. Prefer a union parameter when the return type and behavior do not need distinct call signatures.

</>
Copy
function parse(value: string): number;
function parse(value: number): string;
function parse(value: string | number): string | number {
  return typeof value === "string"
    ? Number(value)
    : String(value);
}

43. What is type variance, and why does it matter?

Variance describes how relationships between component types affect relationships between constructed types. It is especially important for function parameters, callbacks, arrays, and generic APIs. Under strict function checking, parameter compatibility is handled more cautiously to prevent a callback that accepts a narrower input from being used where a broader input may be supplied.

44. What is the difference between mutable arrays and readonly arrays?

A mutable T[] allows methods such as push and index assignment. A readonly T[] or ReadonlyArray<T> prevents mutation through that reference. A mutable array can be passed to a readonly parameter, but the reverse assignment is unsafe because the receiving code might mutate it.

45. How do you model asynchronous function return types?

An async function always returns a Promise. Its annotated return type should therefore be Promise<T>, where T is the value produced after awaiting. A function that completes without a useful value returns Promise<void>.

</>
Copy
async function saveRecord(): Promise<void> {
  await fetch("/api/records", {
    method: "POST"
  });
}

46. What is the difference between enums and string literal unions?

A regular TypeScript enum produces a runtime JavaScript object. A union of string literals exists only in the type system and emits no object. Many codebases prefer literal unions with as const objects because they integrate directly with JavaScript, but enums remain useful when a runtime named collection and enum semantics are desired.

47. When should you avoid overly complex TypeScript types?

A type is too complex when it becomes harder to understand, maintain, diagnose, or compile than the problem it solves. Prefer direct domain models, small reusable helpers, clear generic constraints, and runtime validation at boundaries. Advanced conditional or mapped types are justified when they remove repeated errors without hiding the business meaning.

Practical TypeScript Coding Interview Exercises

48. Write a type-safe function that groups items by a property

</>
Copy
function groupBy<T, K extends PropertyKey>(
  items: readonly T[],
  getKey: (item: T) => K
): Record<K, T[]> {
  return items.reduce((groups, item) => {
    const key = getKey(item);
    (groups[key] ??= []).push(item);
    return groups;
  }, {} as Record<K, T[]>);
}

A strong explanation should mention why T preserves the item type, why K is constrained to PropertyKey, and why the input is readonly even though the newly created grouped arrays are mutable.

49. Create a type that makes selected properties optional

</>
Copy
type OptionalKeys<T, K extends keyof T> =
  Omit<T, K> & Partial<Pick<T, K>>;

interface Order {
  id: number;
  customerId: number;
  note: string;
}

type OrderDraft = OptionalKeys<Order, "id" | "note">;

50. Implement an exhaustive state renderer

</>
Copy
type LoadState<T> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; error: Error };

function renderState<T>(state: LoadState<T>): string {
  switch (state.status) {
    case "idle":
      return "Not started";
    case "loading":
      return "Loading";
    case "success":
      return JSON.stringify(state.data);
    case "error":
      return state.error.message;
    default: {
      const unreachable: never = state;
      return unreachable;
    }
  }
}

TypeScript Interview Preparation by Experience Level

Freshers should be ready to explain annotations, inference, interfaces, unions, narrowing, classes, generics, compiler output, and basic tsconfig.json settings. Experienced developers should also be able to discuss API-boundary validation, utility and conditional types, module resolution, declaration files, library typing, strictness migrations, type-design trade-offs, and maintainability.

For senior roles, interviewers often care less about recalling syntax and more about whether the candidate can choose a simple, safe model for real application code. Explain why a type exists, what runtime assumptions remain, how the design behaves when requirements change, and where validation should occur.

TypeScript Interview Questions for Automation Testing

For Playwright, WebdriverIO, Cypress, or similar test stacks, prepare to discuss typed page objects, fixture types, test-data models, environment configuration, asynchronous return types, union-based test states, and safe parsing of API responses. Automation code should not hide untrusted data behind assertions; validate external responses and keep selectors, fixtures, and page actions represented by clear types.

</>
Copy
interface LoginCredentials {
  username: string;
  password: string;
}

interface LoginPage {
  login(credentials: LoginCredentials): Promise<void>;
}

TypeScript Interview FAQs

How many TypeScript questions are usually asked in an interview?

There is no fixed number. A frontend or Node.js interview may mix TypeScript questions with JavaScript, framework, testing, architecture, and coding tasks. Prepare to explain a smaller set of concepts deeply rather than memorizing one-line answers.

Are TypeScript interviews different for freshers and experienced developers?

Yes. Fresher interviews usually emphasize language basics and small code examples. Experienced interviews are more likely to cover generic API design, runtime validation, compiler configuration, declaration files, module systems, migration strategy, and trade-offs in large codebases.

Should I learn advanced conditional types for a TypeScript interview?

Learn the purpose and basic syntax, but prioritize everyday skills first: narrowing, generics, utility types, strict mode, object modeling, and safe external-data handling. Advanced type programming matters more for library, platform, and senior TypeScript roles.

Is TypeScript enough to validate API data?

No. TypeScript types do not validate runtime data. Validate API responses, form submissions, storage values, and environment variables before treating them as trusted domain objects.

What is the best way to answer a TypeScript coding question?

State the input and output types, identify nullable or untrusted values, choose the simplest appropriate abstraction, write the implementation, and explain the compiler guarantees. Also identify what still requires runtime checking and mention meaningful edge cases.

Editorial QA Checklist for TypeScript Interview Content

  • Confirm that every code sample is valid TypeScript and uses a PrismJS-compatible language-typescript class.
  • Verify that answers distinguish compile-time type checking from runtime JavaScript behavior.
  • Check that any, unknown, never, void, null, and undefined are not described as interchangeable.
  • Ensure interface and type-alias comparisons mention declaration merging without claiming that one is universally better.
  • Confirm that API-response examples include runtime validation rather than relying only on a type assertion.
  • Review tsconfig.json examples against the intended browser, Node.js, or bundler environment before using them in a real project.
  • Check that utility-type, generic, and narrowing examples explain the type relationship they preserve.
  • Keep version-specific TypeScript features separate from language fundamentals when interview requirements target an older codebase.