Junior — 25 questions
These are asked in nearly every first-round TypeScript screen. Answer each out loud before opening it; an answer only recognised when read is not one that survives being asked under pressure.
JuniorWhat is the difference between interface and type?
Both describe object shapes and mostly overlap. Interfaces can be reopened later through declaration merging and read naturally for public object or class contracts; type can alias anything — unions, tuples, primitives, mapped types — not only objects. A common rule of thumb: default to interface for object shapes that might be extended, type for everything else, unions especially.
What they are really testing: Whether they know both exist for real reasons rather than picking one out of habit.
JuniorWhat does the strict compiler flag do?
It turns on a family of stricter checks together — noImplicitAny, strictNullChecks, strictFunctionTypes, strictPropertyInitialization and more. Without it, an untyped value silently becomes any and null/undefined are assignable to almost everything, which removes most of the value of using TypeScript at all.
What they are really testing: Whether they know strict is a bundle of flags, not one switch, and that turning it off is a trap rather than a shortcut.
JuniorWhat is type erasure?
TypeScript types exist only while tsc is checking the code; the compiled JavaScript carries no trace of them — no runtime type information, nothing like typeof MyInterface. This is why a type or interface can never be used to distinguish objects at runtime; that needs a real value, such as a string tag or an instanceof check.
What they are really testing: Whether they understand TypeScript adds zero runtime cost, and the direct consequence that a type can never gate runtime logic.
JuniorWhat is the difference between any and unknown?
any disables type checking entirely — methods can be called on it, it can be assigned anywhere, and the compiler trusts every use. unknown is type-safe: a value of any shape can be held in it, but nothing can be done with it until its type is narrowed first, with typeof, instanceof, or a type guard.
What they are really testing: The single most common line between a junior and a mid-level answer — do they reach for unknown at API boundaries instead of any.
JuniorWhat is the never type used for?
It represents a value that can never occur — a function that always throws, or one that never returns because it loops forever, or a variable narrowed until no possibilities remain. It shows up most often as the result of exhaustive narrowing, and is used deliberately in a switch’s default case to make the compiler flag any union member left unhandled.
What they are really testing: Whether it has been seen used for exhaustiveness checking, not only described as an abstract curiosity.
JuniorWhat is a generic, in one sentence?
A placeholder type parameter that lets a function, class or type work with any type while keeping the relationship between its inputs and outputs — function first<T>(items: T[]): T returns whatever type was given it, so calling it with string[] gives back a string, not any.
What they are really testing: Whether they connect generics to preserving type information end to end, rather than calling them a template with no clear purpose.
JuniorWhat is a union type?
A type that can be one of several types, written A | B — string | number means either one. A method that is not common to every member cannot be called until the union is narrowed to which one is actually present.
What they are really testing: Basic syntax fluency.
JuniorWhat is an intersection type?
A type that combines several types into one, written A & B — the result must satisfy every member at once. It is used to compose smaller interfaces into a larger required shape, for example type Admin = User & { permissions: string[] }.
What they are really testing: Whether union and intersection can be told apart by what a value must satisfy — one of, versus all of.
JuniorWhat does a ? after a property name mean?
The property is optional — it may be omitted entirely, and its type is really T | undefined. Reading it without a guard needs a null check or optional chaining, since strictNullChecks flags using it as if it were always present.
What they are really testing: Fluency with syntax that appears in nearly every interface.
JuniorWhat does readonly do on a property?
It prevents reassignment after the object is created — obj.field = x is a compile error outside the constructor. It is a compile-time guarantee only; nothing stops the property being mutated through a cast or from code outside TypeScript's view, so it documents intent more than it enforces safety.
What they are really testing: Whether they know it is compile-time only, not a runtime freeze — often confused with Object.freeze.
JuniorWhat does a TypeScript enum compile to?
A regular numeric or string enum compiles to a real JavaScript object, with both forward and reverse mappings for numeric enums (Colors.Red === 0 and Colors[0] === "Red"), so it has an actual runtime footprint, unlike almost everything else in TypeScript. const enum is inlined at compile time and leaves no object behind, but is incompatible with some build tools that use isolated-file transpilation.
What they are really testing: Whether they know enums are one of the few TypeScript features that survives compilation as real code.
JuniorWhat is a literal type?
A type that is one specific value rather than a category — type Direction = "up" | "down" restricts a variable to exactly those two strings, not any string. Combined into unions, literal types are how TypeScript models enum-like values without a runtime enum.
What they are really testing: Connects directly to discriminated unions, covered at mid level.
JuniorWhat is the difference between a type assertion (as) and an actual type conversion?
as tells the compiler "trust me, treat this value as this type" — it performs no runtime check or conversion, it only silences the checker. Number(x) or String(x) actually convert the value. Asserting the wrong type compiles cleanly and fails at runtime exactly where a real bug would.
What they are really testing: Whether they know as is a promise made to the compiler, not a safety net.
JuniorWhat is a tuple type?
A fixed-length array where each position has its own type — [string, number] is exactly a string followed by a number, not an array of either. Useful for things like a [value, setValue] pair, where position itself carries meaning.
What they are really testing: Whether they have used one in practice, typically via a library, rather than only recognising the syntax.
JuniorWhat is the difference between a function returning void and one returning undefined?
void means "the return value should be ignored" — callback-shaped code such as a forEach handler or an event listener uses it, and a function can even return something and still be assignable to a void-typed slot. undefined is a real, checkable type; declaring it as the return type means callers are expected to look at the always-undefined result.
What they are really testing: A subtle distinction most juniors have not needed until typing a callback parameter themselves.
JuniorCan two functions with the same name but different parameter types coexist in TypeScript?
Yes, through function overload signatures — several signature declarations followed by one implementation whose parameters are typed loosely enough to satisfy all of them. Callers only ever see the specific overloads, not the implementation signature, so autocomplete matches whichever one they are calling.
What they are really testing: Recognition of the feature, even without having designed one — rarely needed at junior level.
JuniorWhat is a type guard?
A runtime check that narrows a variable's type within a block — after if (typeof x === "string"), TypeScript treats x as string for the rest of that branch. It is how a union type is narrowed back down to something specific enough to use.
What they are really testing: Whether narrowing is understood as something TypeScript infers from ordinary JavaScript checks, not special syntax.
JuniorHow does typeof narrow a type?
Inside if (typeof value === "number"), TypeScript narrows value to number for that branch — it only works for the primitive categories typeof can distinguish (string, number, boolean, undefined, function, object, symbol, bigint), not for telling two object shapes apart.
What they are really testing: Whether the limits of typeof narrowing are known — where it stops working is the natural follow-up.
JuniorHow does instanceof narrow a type?
if (error instanceof RangeError) narrows error to RangeError inside that block. It works because instanceof checks the prototype chain at runtime, something TypeScript can trust since there is a real class behind it, unlike a purely structural type.
What they are really testing: Whether class-based narrowing is connected to typeof's primitive-only narrowing as a distinct mechanism.
JuniorWhat does ! after an expression do — the non-null assertion operator?
It tells the compiler "this is not null or undefined, stop warning me" — document.getElementById("x")!.focus(). It performs no runtime check; being wrong throws exactly where a real null bug would, just later and with less context than a real guard would have given.
What they are really testing: Whether it is understood as a compiler-only suppression, and when it is a code smell versus genuinely necessary — DOM APIs are the usual legitimate case.
JuniorWhat is structural typing, and how does it differ from nominal typing?
TypeScript compares types by shape — two objects with the same properties are compatible regardless of what either is named or whether one was ever declared to implement the other. Nominal typing, as in Java or C#, instead requires an explicit declaration to be considered compatible. This is why an object literal with the right fields satisfies an interface without ever mentioning it.
What they are really testing: Whether they understand why TypeScript accepts values that were never declared against the interface — the most surprising thing to anyone coming from a nominally-typed language.
JuniorWhat is the difference between number[] and Array<number>?
None — they are two syntaxes for the exact same type. T[] is the shorthand generally preferred for simple element types; Array<T> is sometimes clearer for more complex element types, such as a union or a function type.
What they are really testing: Confirms they know it is purely stylistic, not two different types.
JuniorHow do you type a function parameter that has a default value?
TypeScript infers the type from the default itself — function greet(name = "friend") infers name: string — so an explicit annotation is often unnecessary. One is only needed when the inferred type is narrower than how the parameter is actually meant to be used.
What they are really testing: Whether they over-annotate out of habit, the same instinct the "let it infer" rule from Module 00 already warns against.
JuniorWhat does noImplicitAny do, specifically?
It errors on any parameter, variable or return value whose type TypeScript cannot infer and that has no annotation, instead of silently treating it as any. It is one of the flags bundled into strict, and is usually the very first error a real, previously untyped JS file produces once converted to TS.
What they are really testing: The exact flag behind TS7006, since it is the single most common first error in any migration.
JuniorWhat is the difference between const x = 5 and const x = 5 as const?
For a plain primitive like 5, const alone already narrows it to the literal type 5 rather than widening to number. The real difference shows on objects and arrays: const p = { x: 1 } infers { x: number }, while const p = { x: 1 } as const infers { readonly x: 1 } — every property becomes readonly and keeps its specific literal type instead of widening.
What they are really testing: Whether as const has been used for literal-type inference on objects, arrays or tuples — a very common modern pattern for config objects and action types.
