advanced

Structural typing and OOP

Explain why TypeScript compatibility is based on shape rather than declared inheritance and how that affects class-based design.

TypeScript uses structural typing: compatibility is by shape, not declared inheritance. A class instance is assignable to an interface if it has the required members—no `implements` keyword required at runtime. This differs from nominal languages like Java where type names must match.

Design impact: duck typing enables flexible adapters but allows accidental compatibility when shapes collide.

On interviews: show two unrelated classes satisfying the same interface and discuss when branded types help.

Common pitfalls: assuming `implements` enforces runtime checks, excess property errors on object literals, and class hierarchies that TypeScript considers compatible too broadly.

The trade-off is flexibility versus catching wrong-type mistakes only at compile time if shapes align.

Checklist:

  • Explain shape-based assignability.
  • Use branded types for critical IDs.
  • Separate DTO shapes from domain types deliberately.