Suggest an editImprove this articleRefine the answer for “Structural typing in interfaces”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Structural typing** is a principle by which type compatibility is determined by shape (structure), not by the type's name. **Key point:** if an object contains all the required properties of the required types, it is considered compatible with the interface, even if it is not declared as that type.Shown above the full answer for quick recall.Answer (EN)Image## 1. What is structural typing > **Structural typing** is a principle by which > type compatibility is determined **by their shape (structure)**, > not by the type's name. Put simply: > if an object **looks like** an interface, > TypeScript considers it to **match that interface**. --- ### Example ```javascript interface User { id: number; name: string; } const person = { id: 1, name: "Tim", age: 25, }; // It can be assigned - the structure matches const u: User = person; ``` > Although `person` **is not declared as** `User`, > TypeScript sees that it **has all the required fields** (`id` and `name`), > and considers the types compatible. > > Extra fields (`age`) don't get in the way. --- ## 2. Unlike nominal typing In some languages (for example, Java, C#, Swift) type compatibility is checked **by name** or **by declaration**, not by structure. ### Example (how it would be with nominal typing): ```javascript class User { int id; String name; } class Person { int id; String name; } // Error - the types are different, even though the fields are the same User u = new Person(); ``` > In TypeScript, it's the opposite - **what matters is that the structure matches**. > This makes the language more flexible and more "utilitarian". --- ## 3. How TypeScript checks structural compatibility TypeScript compares the **shape of objects**, not their "origin". ### Example: ```javascript interface Point { x: number; y: number; } const coord = { x: 10, y: 20, z: 30 }; const p: Point = coord; // OK ``` > The check is: > "Does `coord` have the `x` and `y` properties of the required types?" - > Yes -> so it matches `Point`. --- ## 4. Structural typing also works with functions ```javascript interface Logger { (msg: string): void; } function logToConsole(message: string) { console.log(message); } const logger: Logger = logToConsole; // OK ``` > TypeScript checks the **function signature**, > not what it's called. --- ## 5. Why this matters Thanks to structural typing: - you can use **inline objects** without explicit interfaces; - types become **flexible and compatible**; - it's easy to work with **external data (API, JSON)**; - there's less "ceremony" (less boilerplate code). --- ## Example: "duck typing" > "If something **quacks like a duck** and **looks like a duck**, > TypeScript considers it a **duck**." ```javascript interface Duck { quack(): void; } const animal = { quack: () => console.log("Quack!"), }; const d: Duck = animal; // OK - the structure matches ``` --- ## 6. How structural typing affects interfaces Interfaces in TypeScript: - **are not real entities at runtime**; - **only define the shape of data**; - work **on the principle of structural matching**. ### Example: ```javascript interface Car { wheels: number; } interface Truck { wheels: number; } let c: Car = { wheels: 4 }; let t: Truck = c; // OK - the structure matches ``` > Although `Car` and `Truck` are different interfaces, > TypeScript considers them compatible, > because they have the same structure. --- ## 7. When this can be unexpected Sometimes structural typing leads to "too flexible" behavior: ```javascript interface Point2D { x: number; y: number; } interface Point3D { x: number; y: number; z: number; } const point3D: Point3D = { x: 1, y: 2, z: 3 }; const p2d: Point2D = point3D; // OK ``` > TypeScript has no objection - after all, `point3D` has everything `Point2D` needs. > But this can lead to logical errors if you expected a 2D point. --- ## 8. Structural typing and classes Classes are also structurally typed. That is, it doesn't matter "what" they inherit from - what matters is **what's in them**. ```javascript class Person { name = "Tim"; } interface Named { name: string; } let p: Named = new Person(); // OK - the fields match ``` > Even though `Person` doesn't "implement" the `Named` interface, > it's still compatible with it. --- ## Summary > **Structural typing** is a way of checking types in TypeScript > in which compatibility is determined **by structure**, not by name. > > That is: > if an object *contains all the required properties* of the required types, > it is **considered compatible** with the interface. > > Benefits: > > - flexibility and convenience when working with data; > - less code (no need to explicitly "implements" everything); > - ideal for JSON, APIs, functions, and objects. > > Downside: > > - you can accidentally pass "extra" data and not notice a logic mismatch.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.