The short answer: TypeScript interviews check that you can model data with types (type aliases and interfaces, unions, generics), make the compiler prove things for you (narrowing, discriminated unions, exhaustiveness with never), and use the type system’s tools (keyof, mapped and conditional types, utility types, satisfies). Many teams also ask what’s current: TypeScript 7.0, released July 8, 2026, is the compiler rewritten in Go, and Node.js now runs TypeScript files by stripping their types. The answers below are checked against the TypeScript handbook, the TypeScript team’s release posts and the Node.js docs, with sources at the end.
Before TypeScript, make sure the JavaScript underneath is solid: see our JavaScript interview questions.
Fundamentals
“What is TypeScript, and what does it not do?”
TypeScript is JavaScript with a static type system: the compiler checks your types, then emits plain JavaScript. The types don’t exist at runtime. The handbook is explicit that type assertions “are removed by the compiler and won’t affect the runtime behavior,” and that there won’t be an exception “if the type assertion is wrong.” So data from outside your program (an API response, a form, JSON.parse) still needs runtime validation, with your own checks or a schema library.
“Type alias or interface?”
Both describe object shapes and are mostly interchangeable. The handbook’s key distinction: “a type cannot be re-opened to add new properties,” while interfaces support declaration merging (declaring the same interface twice combines them). Type aliases can also name unions, tuples and primitives (type Id = string | number), which interfaces can’t. The handbook notes that interfaces with extends “can often be more performant for the compiler” than intersections, and suggests: “use interface until you need to use features from type.”
“any, unknown and never?”
anyswitches checking off: “usinganydisables all further type checking.” Avoid it; it spreads.unknownis the safe “could be anything”: you can assign anything to it, but you must narrow it before using it. Use it for untrusted input.neveris the type with no values: a function that always throws, or the leftover after every case of a union has been handled, which is how exhaustiveness checks work.
“What is structural typing?”
TypeScript compares types by their shape, not their name: an object with the right properties is accepted even if it was never declared as that type. One exception surprises people: an object literal with extra properties is an error (excess property checking), but the same object passed through a variable is fine. Puzzle 4 below shows it.
Narrowing and unions
“How does narrowing work?”
TypeScript follows your control flow and refines a union inside each branch. The handbook lists the tools: typeof (for primitives), truthiness, equality (x != null removes both null and undefined), the in operator, instanceof, assignments, and type predicates, functions that return pet is Fish:
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
“What’s a discriminated union, and how do you make a switch exhaustive?”
A union whose members share a literal property, the discriminant:
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 unhandled: never = shape; // error here if a new kind is added
return unhandled;
}
}
}
Add a triangle to Shape without a case, and the compiler reports that it isn’t assignable to never. This is the pattern interviewers most want to see for state machines, reducers and API responses.
“Enums or union types?”
A union of string literals (type Status = 'idle' | 'loading' | 'done') disappears at compile time and works with every tool. An enum generates runtime code, which matters more now: Node.js’s built-in TypeScript support rejects enums, and the erasableSyntaxOnly compiler option flags them. Many teams prefer unions, or an object with as const when they need runtime values.
Generics and type-level tools
“Explain generics and constraints.”
Generics let a function or type work with many types while keeping the relationship between them:
function first<T>(items: T[]): T | undefined {
return items[0];
}
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
K extends keyof T is a constraint: key must be one of obj’s property names, and the return type is the type of that property, so getProp(user, 'age') is a number and getProp(user, 'nope') is a compile error.
“What are keyof, typeof and indexed access types?”
keyof T is the union of T’s property names; typeof value (in a type position) gives the type of a value; T['name'] is the type of one property. Together they let you derive types from existing code instead of repeating them: type Config = typeof defaultConfig.
“Mapped and conditional types?”
A mapped type builds a new object type from the keys of another: { [K in keyof T]?: T[K] } is how Partial works. A conditional type chooses a type based on a test, T extends U ? X : Y, and infer captures part of a type inside that test. Conditional types distribute over unions, which is why Exclude<'a' | 'b', 'a'> is 'b'.
“Which utility types do you use?”
Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, ReturnType, Parameters and Awaited cover most needs. Be ready to implement a few (see the exercises below).
“What does satisfies do?”
It checks that a value matches a type without changing the value’s inferred type:
const palette = {
red: [255, 0, 0],
green: '#00ff00',
} satisfies Record<string, string | number[]>;
palette.green.toUpperCase(); // OK: green is still known to be a string
With a type annotation (const palette: Record<...> = ...), palette.green would be string | number[] and the call would need a check first.
Configuration and tooling
“Which tsconfig options matter most?”
strict: turns on the strict family (strictNullChecks,noImplicitAnyand more). Since TypeScript 6.0 it’s on by default.noUncheckedIndexedAccess: not part ofstrict; makesarray[i]and record lookups includeundefined, which catches real bugs.moduleandmoduleResolution:nodenextfor Node.js,bundlerfor code that goes through a bundler. The oldnode(node10) resolution was deprecated andclassicremoved in 6.0; both are errors in 7.0.verbatimModuleSyntaxanderasableSyntaxOnly: keep the output close to what you wrote, which is what Node.js’s type stripping expects.
“What changed in TypeScript 6.0 and 7.0?”
TypeScript 6.0 (March 23, 2026) was the bridge release: the last one built on the JavaScript codebase. It changed defaults (strict on, module set to esnext, types empty, so you list packages such as node), deprecated target: es5 and baseUrl as a lookup root, dropped AMD, UMD and SystemJS output, and removed outFile.
TypeScript 7.0 (July 8, 2026) is a native port of the compiler written in Go, which the team describes as “a 10x faster native port,” typically “between 8x and 12x on full builds,” with parsing, checking and emitting running in parallel. Options deprecated in 6.0 are now errors. It ships without a programmatic API (a new one is expected in 7.1, in beta since October 20, 2026), so some editor integrations, such as template checking for Vue, Svelte and Angular, still rely on 6.0, which stays available as @typescript/typescript6.
“Can Node.js run TypeScript directly?”
Yes, by type stripping: Node.js replaces type annotations with whitespace and runs the result. It’s on by default since v22.18.0 and v23.6.0 and marked stable since v24.12.0 and v25.2.0. It does no type checking, so you still run tsc (usually with noEmit) in CI, and it only accepts erasable syntax: enums, namespaces with runtime code and parameter properties fail. Use import type for type-only imports.
“How do you add types for a JavaScript library?”
Many packages ship their own .d.ts declaration files; for the rest, install community types from DefinitelyTyped (npm i -D @types/the-package), or write a small declare module 'the-package' declaration yourself.
TypeScript with React
Typical questions: typing props (type ButtonProps = { label: string; onClick: () => void }), state that starts empty (useState<User | null>(null)), events (React.ChangeEvent<HTMLInputElement>), children, and generic components such as a typed List<T>. Use a discriminated union for component state ({ status: 'loading' } | { status: 'error'; error: string } | { status: 'done'; data: User }) so impossible combinations can’t be written. For the React side, see our React interview questions.
Type puzzles (“what’s the type?”)
1. Literal widening
const a = 'hello'; // type: 'hello'
let b = 'hello'; // type: string
const c = ['a', 1]; // type: (string | number)[]
const d = ['a', 1] as const; // type: readonly ['a', 1]
2. keyof
type K = keyof { id: number; name: string }; // 'id' | 'name'
3. Distributive conditional types
type IsString<T> = T extends string ? 'yes' : 'no';
type R = IsString<string | number>; // 'yes' | 'no' (checked once per member)
4. Excess property checks vs structural typing
interface Point { x: number; y: number }
const p: Point = { x: 1, y: 2, z: 3 }; // Error: object literal may only specify known properties
const obj = { x: 1, y: 2, z: 3 };
const q: Point = obj; // OK: extra properties are allowed through a variable
Coding exercises: implement the utility types
type MyPartial<T> = { [K in keyof T]?: T[K] };
type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };
type MyExclude<T, U> = T extends U ? never : T;
type MyOmit<T, K extends keyof T> = MyPick<T, MyExclude<keyof T, K>>;
type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never;
type MyAwaited<T> = T extends PromiseLike<infer U> ? MyAwaited<U> : T;
Follow-ups: a DeepReadonly (recurse into object properties), a typed groupBy<T, K extends PropertyKey> function, and a type-safe event emitter where emit('login', payload) checks the payload against an event map. Explain each line: interviewers care that you know why K extends keyof T is needed, not just the syntax.
Behavioral questions for TypeScript developers
Use the STAR method with a real example:
- “Tell me about migrating a JavaScript codebase to TypeScript. How did you roll it out?”
- “Describe a bug the type system caught, or one it couldn’t.”
- “When have you chosen not to add a complex type?”
- “How do you keep types for API responses in sync with the back end?”
More: our front-end developer interview questions and full-stack developer interview questions.
Frequently asked questions
What TypeScript questions are asked in interviews?
Should I use type or interface?
What is TypeScript 7?
Does Node.js type-check TypeScript files?
Do types protect me from bad data at runtime?
Can Huru help me practice TypeScript interview questions?
Sources
- TypeScript Handbook: Everyday Types (type aliases vs interfaces,
any, type assertions) and Narrowing. Read on 28 October 2026. - TypeScript team blog: Announcing TypeScript 6.0 (March 23, 2026) and Announcing TypeScript 7.0 (July 8, 2026). Read on 28 October 2026.
- Node.js documentation, Modules: TypeScript (type stripping). Read on 28 October 2026.