Lesson 29 of 80
TypeScript code lives in two separate, parallel worlds that happen to share the same names and often the same syntax — confusing the two is the root cause behind a whole category of 'why doesn't this compile' surprises.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 2
Why are enums unusual in the same way classes are, compared to interfaces or type aliases?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Every identifier in a TypeScript file exists in one (or both) of two separate namespaces:
class User { name: string = ""; }
const a: User = new User(); // "User" on the right = value space (the constructor, calling it)
// "User" on the left = type space (the type of `a`)
function f(x: typeof a) {} // typeof crosses FROM value space INTO type space
The same identifier, User, means genuinely different things depending on position — this is only possible because a class declaration creates an entry in both namespaces at once (a real constructor function, and a type describing its instances). An interface only ever creates a type-space entry; a const only ever creates a value-space entry.
Every identifier lives in type-space (compile-time, erased before runtime), value-space (real at runtime), or both.
Status.Active is a real runtime value, and Status is also usable as a type, which is exactly why enums generate actual JavaScript while interfaces don't.__brand field lives purely in type-space, contributing nothing to value-space, so it can shape how the type checker reasons about a value without adding a single byte to what actually exists at runtime.Explicitly naming "type space vs value space" as the underlying reason for a specific confusing error is a genuinely senior-level move — it reframes a pile of individually-memorized gotchas (enums are weird, typeof is overloaded, branding works) as one consistent mental model.