TypeScript course menu
Intermediate TypeScript Interview Questions and Answers
Intermediate TypeScript interview questions with tested answers: narrowing, discriminated unions, generics and constraints, keyof and typeof, utility types, type guards, structural typing, access modifiers, as vs satisfies, and declaration files.
On this page
- 1. What is narrowing? Name some ways to narrow a type.
- 2. What is a discriminated union? Show an example.
- 3. What are generics, and why use them?
- 4. How do you constrain a generic?
- 5. Explain keyof and typeof in types.
- 6. Name some utility types and their uses.
- 7. What is a type guard? Write one.
- 8. What is structural typing?
- 9. What is the difference between private and #private?
- 10. What is the difference between as and satisfies?
- 11. What is the non-null assertion operator?
- 12. What is a .d.ts file?
- 13. How do you make a switch statement exhaustive?
- 14. How do you type data from an API?
- Keep going
These questions check whether you can use TypeScript to model real data and write reusable code. Interviewers often ask you to write a small type or function, so try each one before opening the answer.
1. What is narrowing? Name some ways to narrow a type.#
Show solution
Narrowing is TypeScript refining a union type inside a branch based on runtime checks. Ways to narrow: typeof (primitives), instanceof (classes), in (property presence), equality checks (=== null), truthiness checks, Array.isArray, discriminant property checks, and custom type guard functions (value is T).
2. What is a discriminated union? Show an example.#
Show solution
A union of object types that share a literal property identifying each member. Checking that property narrows to one member:
type Result = { ok: true; value: number } | { ok: false; error: string };
function show(r: Result): string {
return r.ok ? `value ${r.value}` : `error ${r.error}`;
}
console.log(show({ ok: true, value: 3 }), show({ ok: false, error: "bad input" }));value 3 error bad inputCombined with a never check in a switch default, it makes handling every case mandatory.
3. What are generics, and why use them?#
Show solution
Generics add type parameters so one function, class or type works with many types while preserving which type is used. function first<T>(items: T[]): T | undefined returns a number for a number array and a string for a string array, which any could not express. Built-in examples are Array<T>, Promise<T> and Map<K, V>.
4. How do you constrain a generic?#
Show solution
With extends: function longest<T extends { length: number }>(a: T, b: T): T accepts only types with a length. A common pattern is K extends keyof T for type-safe property access:
function get<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "Asha", age: 21 };
console.log(get(user, "age") + 1);225. Explain keyof and typeof in types.#
Show solution
keyof T is the union of T's property names. In a type position, typeof value gives the type of a variable. Together, keyof typeof obj gives the keys of an object value, which is useful for constants defined with as const. T[K] (indexed access) gives the type of a property.
6. Name some utility types and their uses.#
Show solution
Partial<T> (update payloads), Required<T>, Readonly<T>, Pick<T, K> and Omit<T, K> (select or remove properties, for example Omit<User, "password">), Record<K, V> (dictionaries and lookup tables), Exclude and Extract (filter unions), NonNullable<T>, ReturnType<F>, Parameters<F> and Awaited<T>.
7. What is a type guard? Write one.#
Show solution
A function that returns a type predicate, value is T, so that a true result narrows the value:
interface Admin { role: "admin"; permissions: string[] }
function isAdmin(value: unknown): value is Admin {
return typeof value === "object" && value !== null && (value as Admin).role === "admin"
&& Array.isArray((value as Admin).permissions);
}
const data: unknown = { role: "admin", permissions: ["delete"] };
if (isAdmin(data)) console.log(data.permissions[0]);deleteTypeScript trusts the predicate, so its checks must be correct.
8. What is structural typing?#
Show solution
TypeScript compares types by their shape (members), not by name or declaration. Any object with the required properties is compatible, even if it was never declared as that type. Fresh object literals are additionally checked for unknown (excess) properties to catch typos.
9. What is the difference between private and #private?#
Show solution
TypeScript's private is enforced only at compile time; at runtime it is a normal property that can be read with JavaScript. JavaScript's #private fields are enforced by the runtime and cannot be accessed outside the class at all.
10. What is the difference between as and satisfies?#
Show solution
value as T tells the compiler to treat a value as T without checking it (only obviously incompatible assertions are rejected), and the value's type becomes T. value satisfies T checks that the value matches T but keeps the value's more precise inferred type. satisfies is safe; as moves responsibility to you.
11. What is the non-null assertion operator?#
Show solution
A postfix ! removes null and undefined from a type (map.get(key)!). It performs no runtime check, so if the value is missing the program can crash or produce wrong results. Prefer narrowing, optional chaining or ?? defaults.
12. What is a .d.ts file?#
Show solution
A declaration file containing only types, describing JavaScript code that exists elsewhere. Libraries ship them (or the community provides them as @types/... packages on npm) so TypeScript can type-check code that uses them. You can write declare module "name" declarations for untyped packages.
13. How do you make a switch statement exhaustive?#
Show solution
Assign the value to a never variable in the default branch. If any union member is not handled, it is still possible in default, and assigning it to never is a compile error that names the missing case.
14. How do you type data from an API?#
Show solution
response.json() returns any, so writing const user: User = await response.json() is an unchecked assumption. Safer: treat it as unknown and validate with a type guard or a schema library (Zod, Valibot), which checks at runtime and produces a typed value.
Keep going#
Continue with the advanced TypeScript questions, or browse every question with hints on the TypeScript interview page.
Finished this lesson?