liveBook · Manning

Shape type

As explained in Essential TypeScript 5, Third Edition

A shape type specifies an object type through a particular combination of property names and value types.

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

How Essential TypeScript 5, Third Edition covers it

How deep it goes
Works through required, extra, and optional members, aliases, and matching, then connects shapes to unions, intersections, and generic constraints.
Examples
Uses todo-item counts, products with optional members, constructor-created employees, and a generic collection of named items.
What it assumes
Assumes familiarity with JavaScript objects and TypeScript annotations; introduces shape matching through object literals and class-based objects.
What you can do after
Build it from scratch by writing reusable object shapes and applying them to return types, arrays, and generic constraints.
How it connects
Connects shape types to object literals, type aliases, optional properties, type guards, constructor functions, unions, intersections, and generics.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Essential TypeScript 5, Third Edition. The section links point to the parts of the book it draws on.