An object’s shape is the combination of its property names and value types. JavaScript lets an object change after creation: properties can be added or deleted, and a property can receive a value of another type. TypeScript uses shapes to check how objects are used, whether they were created as literals or from classes. This is a type-checking concept here, not an explanation of JavaScript engine “hidden classes.” section 3.5.1 section 10.2
Name a shape for a result
In src/todoCollection.ts, `type ItemCounts = { total: number, incomplete: number }` names the shape of a count result. A `getItemCounts` method can return an object literal matching that shape; its caller reads `getItemCounts().incomplete` to display the number of unfinished items. section 2.2.6
Listing 10.4 Adding an object in the index.ts file in the src folder
let hat = { name: "Hat", price: 100 };
let gloves = { name: "Gloves", price: 75 };
let umbrella = { name: "Umbrella" };
let products = [hat, gloves, umbrella];
products.forEach(prod => console.log(`${prod.name}: ${prod.price}`));
Two products have `name` and `price`, but a third has only `name`. The array’s shared shape does not guarantee `price`, so reading that property for every element produces a compiler error. section 10.2
A shape type can also describe methods and optional properties. A union exposes only members common to its alternatives; an intersection combines their members. Shape-based inference matters with classes, too: an array of instances from different subclasses need not be inferred as an array of their shared superclass. Annotate the array with the superclass type when it must accept other subclasses. section 10.4 section 11.3.7
