A shape type describes an object by the names and types of its properties and methods. TypeScript can check a JavaScript object literal against a shape without requiring the object to come from a class or carry an explicit type annotation. section 2.2.6 section 10.2.2
Return a named shape
In src/todoCollection.ts, `type ItemCounts = { total: number, incomplete: number }` names the result of `getItemCounts()`. The method returns an object literal with those two numeric properties. A caller can then read `collection.getItemCounts().incomplete` to display the number of items still to do. section 2.2.6
Matching a shape has a few practical rules:
- An object must provide every required member with the specified type. Additional properties do not prevent a match: an object with `name`, `price`, and `waterproof` can match a shape that asks for `name` and `price`. section 10.2.2
- A `?` makes a property optional. A missing optional property reads as `undefined`; a missing optional method must be checked before it is called. With `strictNullChecks`, an unchecked call produces a compiler error. section 10.2.2
- The `type` keyword gives a shape a reusable name. An alias can then appear in annotations such as `let products: Product[]` without changing the compiled program’s output. section 10.2.3
Listing 10.11 Using an alias for a shape type in the index.ts file in the src folder
enum Feature { Waterproof, Insulated }
type Product = {
name: string,
price?: number,
hasFeature?(Feature): boolean
};
let hat = { name: "Hat", price: 100 };
let gloves = { name: "Gloves", price: 75 };
let umbrella = { name: "Umbrella", price: 30,
hasFeature: (feature) => feature === Feature.Waterproof };
let products: Product[] = [hat, gloves, umbrella];
products.forEach(prod => console.log(`${prod.name}: ${prod.price} ` +
`${ prod.hasFeature ? prod.hasFeature(Feature.Waterproof) : "false" }`
));
The Product alias groups a required property, an optional property, and an optional method; the caller checks whether the method exists before invoking it. section 10.2.3
Shapes also describe objects made by constructor functions, including methods accessed through a prototype. When narrowing a union of such objects, checking for a distinctive property with `in` can distinguish their shapes where `instanceof` does not serve as a type guard. section 11.2
Constrain a generic collection
`class DataCollection<T extends { name: string }>` accepts different item types that provide a string `name`. Its `getNames()` method can safely read that property without listing every accepted type in a union. section 12.3.3
Shape types can be combined: a union exposes members shared by its constituent shapes, while an intersection brings their members together. This lets object checking extend from a single return value to collections and mixed object types. section 10.4 section 2.2.6
