Structural Typing
Structural typing means TypeScript decides whether two types are compatible by comparing their shape — the properties and methods they have — rather than their declared name, so any object with the required members counts as that type.
Learn Structural Typing in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
A power socket doesn't ask which company made your charger — it only checks that the plug has the right prongs. Any device with a matching plug "fits," regardless of brand or name. Structural typing is the same: TypeScript checks the prongs (the properties), not the label on the box. If the shape fits, it plugs in.
1. Shape Over Name
A function that needs a Point with x and y will accept any object that has those properties — even one you never declared as a Point . There's no implements , no inheritance, no conversion: having the right structure is being the type. This is why TypeScript is described as "structurally typed" and nicknamed "duck typed."
2. Excess Property Checks
Structural typing normally allows extra properties — a wider object fits a narrower requirement. But TypeScript makes one strict exception: when you assign a fresh object literal directly to a typed target, an unexpected property is flagged. That's because a literal with a surprise property is almost always a typo. Route the literal through a variable first and the special check disappears, leaving plain assignability.
3. Assignability: Has at Least What's Required
The core rule is simple: a value is assignable to a type when it has at least every member that type requires. A wider object can stand in for a narrower one, and the extra fields are simply ignored. A direct consequence is that two named types you never related to each other — a Person and a Product — can both satisfy a function that needs only their common shape.
🎯 Your Turn
A robot and a pet share nothing but a name . A function needing only {' '} accepts both. Fill in the blank marked ___ with the shared property, then run it.
No blanks this time — just a brief and a starting outline. Build the sum yourself, run it, and check your output against the example in the comments.
Practice quiz
What does structural typing compare to decide compatibility?
- The declared type name
- The file the type lives in
- The shape - the set of properties and methods
- The order types were declared
Answer: The shape - the set of properties and methods. TypeScript matches types by structure, not by their declared name.
Why is structural typing nicknamed 'duck typing'?
- If it has the right members, it counts as the type - walks/quacks like a duck
- It involves real ducks
- It only works on animals
- It quacks at runtime
Answer: If it has the right members, it counts as the type - walks/quacks like a duck. TypeScript asks what a value can do, not what it is called.
Does an object need to be declared 'a Point' to be used as one?
- Yes, with implements
- Yes, with a class
- Only with as Point
- No - having x and y is enough
Answer: No - having x and y is enough. Any object with the required members satisfies the type; no declaration needed.
When does an excess property check fire?
- On every object
- On a fresh object literal assigned directly to a typed target
- Only inside functions
- Never in strict mode
Answer: On a fresh object literal assigned directly to a typed target. TypeScript flags extra properties only on fresh literals - a deliberate typo catcher.
How can you make an excess-property error go away (legitimately)?
- Assign the literal to a variable first, then assign that variable
- Use any
- Delete the type
- Add @ts-ignore
Answer: Assign the literal to a variable first, then assign that variable. Routing through a variable skips the literal-only check; plain assignability takes over.
What is the core rule of assignability?
- Types must share a name
- Both types need the same number of properties
- A value is assignable if it has at least every member the type requires
- Objects must be frozen
Answer: A value is assignable if it has at least every member the type requires. Has at least the required members = assignable; extras are ignored.
Can a wider object stand in for a narrower required shape?
- No
- Yes - the extra properties are simply ignored
- Only with a cast
- Only if frozen
Answer: Yes - the extra properties are simply ignored. A superset object satisfies a smaller required shape; extra fields don't matter.
Can two unrelated named types be compatible?
- No, names must match
- Only if one extends the other
- Only for classes
- Yes, if their shapes line up (e.g. both have name: string)
Answer: Yes, if their shapes line up (e.g. both have name: string). Structural compatibility means coincidental matching shapes are interchangeable.
How does TypeScript's typing differ from Java/C# nominal typing?
- It is identical
- Nominal typing needs explicit declaration by name; structural only needs the shape
- Structural typing is slower
- Nominal typing ignores names
Answer: Nominal typing needs explicit declaration by name; structural only needs the shape. Nominal systems require declaring a value to be a type by name; TypeScript only checks structure.
If you need two same-shaped types to be incompatible, you should use:
- as const
- Object.freeze
- branded (nominal) types
- an index signature
Answer: branded (nominal) types. Branded types add a unique marker so structurally identical types can't mix.