typestar

Structural typing in TypeScript

Compatibility is about shape, not about names or ancestry.

interface Named {
  name: string;
}

class Person {
  constructor(public name: string, public age: number) {}
}

function greet(named: Named): string {
  return `hello ${named.name}`;
}

console.log(greet(new Person("ada", 36)));
console.log(greet({ name: "grace", extra: true } as Named));

type UserId = string & { readonly brand: unique symbol };

function makeUserId(raw: string): UserId {
  return raw as UserId;
}

function load(id: UserId): string {
  return `loading ${id}`;
}

console.log(load(makeUserId("u-1")));
// load("u-1"); // error: a plain string is not a UserId

How it works

  1. Anything with the right members fits, even from another file.
  2. Extra members are fine, except on a fresh literal.
  3. A branded type is how you get nominal behavior back.

Keywords and builtins used here

The run, in numbers

Lines
27
Characters to type
570
Tokens
145
Three-star pace
95 tpm

At the three-star pace of 95 tokens a minute, this run takes about 92 seconds.

Type this snippet

Step 4 of 5 in Objects & interfaces, step 14 of 23 in Types & annotations.

← Previous Next →