QuestionsTypeScript

Structural typing & excess-property checks

Structural TypingEasyTypeScript

TypeScript uses structural typing, not nominal. What does that mean — and why does an object literal with an extra field error when a variable with the same shape doesn't?

What it tests

Whether you understand duck typing and the object-literal excess-property check that trips people up.

Approach & answer

TS decides compatibility by SHAPE, not by name (nominal). Any value with at least the required members is assignable — a `{ name: string; age: number }` satisfies `{ name: string }` because it has everything the target needs. This is 'duck typing': two independently-declared interfaces with identical members are interchangeable. The surprise is excess-property checking: when you assign an OBJECT LITERAL directly to a typed target, TS flags properties the target doesn't declare — a deliberate lint against typos (`colour` for `color`). Assign through a variable first and the check disappears, because the value is now judged by plain shape-compatibility rather than as a fresh literal. Escape hatches when you genuinely want extra fields: assign to a variable first, add an index signature (`[k: string]: unknown`), or use `as`. The deeper point: structural typing is why generics, utility types, and 'make illegal states unrepresentable' all compose — TS reasons about shapes, so derived and combined types stay compatible automatically. It's also exactly why you sometimes WANT nominal typing (branding) to stop two same-shaped-but-semantically-different types from mixing.

Use this technique when

Passing partial config objects, understanding why a typo errors on a literal but not a variable, deciding when to brand a type.

References

ts