38 questions - Beginner to intermediate

TypeScript interview questions and answers

TypeScript questions come up in almost every Angular interview and most React ones. Interviewers want to see that you use types to catch real bugs, not that you learned the syntax by heart. Keep your answers concrete.

Last updated:

TypeScript basics

What is TypeScript?

TypeScript is JavaScript with a type system on top. You write types, the compiler checks them, and then the types are removed. The browser runs plain JavaScript. So the whole benefit happens before the code runs.

Why use TypeScript instead of JavaScript?

It catches typos and wrong data shapes while you build, not in production. It gives real autocomplete and safe renaming in the editor. It also works as documentation that cannot go out of date. On a big team that saves a lot of time.

What is type inference?

TypeScript works out the type by itself from the value you give. So you do not have to write types everywhere. Write types for function parameters and public return values. Let inference handle simple local variables.

let count = 5;        // inferred as number
count = "five";       // Error

What is the difference between any, unknown and never?

any switches all checking off, so use it only as a last resort. unknown is the safe version: it can hold anything, but you must narrow the type before you use it. never means a value that can never exist, like the return type of a function that always throws.

let a: any = 1; a.foo();          // allowed, may crash
let u: unknown = 1;
// u.toFixed();                    // Error
if (typeof u === "number") u.toFixed(); // fine

What is the difference between null, undefined and strictNullChecks?

With strictNullChecks on, null and undefined are not allowed in a normal type. You must write string | null and then check before use. That one flag stops most "cannot read property of undefined" crashes.

What is a union type and an intersection type?

A union with | means the value is one of these types. An intersection with & means the value has all of these types joined together.

type Status = "idle" | "loading" | "error";
type Admin = User & { permissions: string[] };

What is a literal type?

A literal type allows one exact value only, like "GET". Put a few in a union and you get a safe list of options. That is usually better than an enum.

What is the difference between an enum and a union of literals?

An enum creates real JavaScript at runtime and adds to the bundle. A union of string literals disappears when you compile and is easier to work with. Use a plain union, or const enum, unless you really need the runtime object.

What is a tuple?

A tuple is an array with a fixed length where every position has its own type. React useState returns a tuple: a value and a setter.

const point: [number, number] = [10, 20];
const pair: [string, boolean] = ["ok", true];

What are optional and readonly properties?

A question mark makes a property optional, so it can be missing. readonly stops you changing it after the object is made. Both exist only at compile time.

interface User {
  id: number;
  readonly createdAt: string;
  nickname?: string;
}

Types, interfaces and structure

What is the difference between type and interface?

Both describe the shape of an object. An interface can be opened again later and added to, which is called declaration merging, so it fits public object shapes and classes. A type alias can also describe unions, tuples and mapped types, which an interface cannot. Pick one style and stay with it.

interface Props { title: string; }
interface Props { subtitle?: string; }   // merged, both exist

type Id = string | number;               // interface cannot do this

What is structural typing?

TypeScript compares the shape of types, not their names. If an object has all the required properties with the right types, it fits. It does not have to say that it implements anything.

What is excess property checking?

When you assign an object literal straight away, TypeScript complains about extra properties that are not in the type. This catches typos. If you assign through a variable first, that check is skipped, because then it only checks that the types are compatible.

What are generics?

Generics let one function or type work with many types, while keeping the link between input and output. The caller decides the real type. You get safety without writing the same code again.

function first<T>(items: T[]): T | undefined {
  return items[0];
}
const n = first([1, 2, 3]);      // number | undefined
const s = first(["a", "b"]);     // string | undefined

What is a generic constraint?

A constraint limits what the generic type can be, using extends. You can then safely use those properties inside the function.

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

What is keyof and typeof in the type world?

keyof gives a union of the property names of a type. typeof, used in a type position, takes the type of a value that already exists. Together they let you write code that stays correct when the object changes.

const config = { host: "localhost", port: 8080 };
type Config = typeof config;          // { host: string; port: number }
type Key = keyof Config;              // "host" | "port"

function get<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

What are the common utility types?

Partial makes every property optional. Required does the opposite. Pick keeps only the keys you choose. Omit removes keys. Record builds a key-value map. Readonly locks properties. ReturnType takes the return type of a function.

type Draft = Partial<User>;
type Preview = Pick<User, "id" | "name">;
type Safe = Omit<User, "password">;
type Lookup = Record<string, User>;

What is a mapped type?

A mapped type builds a new type by looping over the keys of another one. Partial and Readonly are written this way inside TypeScript.

type Nullable<T> = { [K in keyof T]: T[K] | null };

What is a conditional type?

A conditional type picks between two types based on a check, using the extends ? : form. Helpers like ReturnType are built this way.

type Unwrap<T> = T extends Promise<infer U> ? U : T;
type A = Unwrap<Promise<string>>; // string

What does infer do?

Inside a conditional type, infer catches a part of the type and gives it a name, so you can return it. It is how you pull the item type out of an array, or the value out of a promise.

Narrowing, safety and classes

What is type narrowing?

Narrowing is TypeScript cutting a union down to a smaller type after a check. typeof, instanceof, the in operator, a truthy check, or comparing a literal field all narrow the type.

function print(value: string | number) {
  if (typeof value === "string") {
    value.toUpperCase();  // string here
  } else {
    value.toFixed(2);     // number here
  }
}

What is a discriminated union?

It is a union of object types that all share one literal field, usually called kind or type. Checking that field narrows the value to exactly one member. It is the cleanest way to model API responses and Redux actions.

type Result =
  | { status: "success"; data: User }
  | { status: "error"; message: string };

function show(r: Result) {
  if (r.status === "success") return r.data.name;
  return r.message;
}

What is a type guard function?

It is a function whose return type is written as "value is Type". When it returns true, TypeScript narrows the variable in the code that called it. It is useful for checking data that came from an API.

function isUser(x: unknown): x is User {
  return typeof x === "object" && x !== null && "id" in x;
}

What is a type assertion and why is it risky?

Writing "as Type" tells the compiler to trust you. Nothing is checked while the code runs. So if the data does not match, the crash comes later and far from the real cause. Prefer narrowing or a validation library.

What does the non-null assertion operator (!) do?

It tells the compiler that a value is definitely not null or undefined. Like as, it is not checked at runtime. Use it only when you can prove it, for example right after a guard.

What are access modifiers in a TypeScript class?

public is the default and is visible everywhere. private is visible only inside the class, and it is checked only at compile time. protected is visible in the class and its subclasses. The JavaScript # private field is enforced at runtime as well.

What is an abstract class?

An abstract class cannot be created directly. It can hold some working methods and leave others empty for subclasses to fill in. Use it when several classes share real code. Use an interface when you only need a contract.

What is a decorator?

A decorator is a function that adds behaviour or extra information to a class, method or property, using the @ syntax. Angular is built on decorators such as @Component, @Injectable and @Input.

@Component({ selector: "app-user" })
export class UserComponent {
  @Input() userId!: string;
}

What is declaration merging?

Two declarations with the same name can be joined into one. Two interfaces merge, and a namespace can add to a class or a function. Libraries use it to extend types like the Express Request object.

What is a .d.ts file?

It is a declaration file. It describes the types of some JavaScript code but holds no working code. It is how you add types to a library that has none, either from DefinitelyTyped as @types/name, or written by you.

Config and real projects

What is tsconfig.json?

It is the settings file for the compiler. It says which files to include, which JavaScript version to output, which module system to use, and how strict to be. When a build acts strangely, check this file first.

What does strict: true turn on?

It turns on a group of flags, including strictNullChecks, noImplicitAny, strictFunctionTypes and strictPropertyInitialization. Turn it on from day one in a new project. In an old project, turn the flags on one at a time.

What does noImplicitAny do?

It makes the compiler complain when it cannot work out a type and would quietly use any. This happens most often on function parameters. It is the single most useful strict flag.

Does TypeScript check types at runtime?

No. All types are removed when you compile. So data from an API or a form still needs a real check while the code runs, written by hand or with a validation library such as Zod.

What is the difference between a compile-time error and a runtime error here?

A compile-time error is TypeScript refusing to build because the types do not fit. Nothing has run yet. A runtime error happens in the browser while the user is on the page. TypeScript helps only with the first kind, which is why checking input still matters.

What is the satisfies operator?

satisfies checks that a value matches a type without widening the value to that type. You keep the exact literal types that were inferred, and you still get the error checking.

const routes = {
  home: "/",
  blog: "/blog",
} satisfies Record<string, string>;
// routes.home is "/" not just string

How do you type an async function?

The return type is a Promise of the value it resolves to. TypeScript works it out on its own, but writing it makes the contract clear.

async function getUser(id: string): Promise<User | null> {
  const res = await fetch("/api/users/" + id);
  return res.ok ? ((await res.json()) as User) : null;
}

How do you migrate a JavaScript project to TypeScript?

Add TypeScript with allowJs so both file types build. Rename a few files at a time, starting with shared utilities. Add types where they help most. Turn strict flags on one by one. Do not do a big rewrite in one go.

Continue with another topic

Practise live

CrackInterviewAI listens to the live interview and gives a structured answer on screen for coding, system design, HR and project questions. Download for Windows.