๐ŸŽ“ A1Learner
๐Ÿ”
0 of 42 lessons completed

TypeScript Structural Typing

Structural typing judges a value by its shape, not by a declared type name. A value fits a type when it carries at least the members that the type requires.

Extra members on a variable are accepted

The variable holds three members and the target shape needs two. The assignment succeeds because the extra member arrived through a variable.

type Point = { x: number; y: number };
const point3d = { x: 1, y: 2, z: 3 };
const point: Point = point3d;
console.log(point.x);
console.log(point.y);

The same members in a fresh literal are refused

A fresh object literal is an object written directly in the assignment. The checker applies the excess property check to fresh literals and refuses the unknown member z.

type Point = { x: number; y: number };
const point: Point = { x: 1, y: 2, z: 3 };
console.log(point);

Fewer parameters is assignable

The target type calls the handler with two arguments. A function that declares only the first parameter ignores the second argument and still fits.

type Handler = (id: number, labelText: string) => string;
const shortHandler: Handler = (id: number) => "id " + id;
console.log(shortHandler(7, "pen"));

More parameters is refused

This function needs a second argument that the target type never supplies. The assignment fails at compile time.

type OneArg = (value: number) => string;
const twoArg: OneArg = (value: number, extra: string) => extra + value;
console.log(twoArg(1));

Example

type Config = { hostName: string; port: number };
const fullConfig = { hostName: "localhost", port: 8080, debug: true };
const config: Config = fullConfig;
type Greeter = (userName: string, punctuation: string) => string;
const greet: Greeter = (userName: string) => "Hi " + userName;
console.log(config.hostName);
console.log(config.port);
console.log(greet("Ana", "!"));

Key points

  • An object variable with extra members is assignable to a smaller shape that it covers.
  • Excess property checks apply to fresh object literals only.
  • A fresh literal with an extra member is refused by an excess property error.
  • A function with fewer parameters is assignable where a type supplies more arguments.
  • A function needing more parameters than the type supplies is refused.

In this example, a variable with an extra debug member fits the smaller Config shape, and a one-parameter function fits a greeter type that supplies two arguments.

Note

Passing a variable first is the standard way to keep extra data while fitting a smaller shape.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท TypeScript Playground

Exercise

Why does an extra member pass through a variable but fail in a fresh object literal?