Two ways to name a type
TypeScript lets you name a type in two ways. type makes a type alias; interface declares an object shape. For plain objects they do the same job. This file uses both, and shows where they differ.
Line 1 is a type alias: ID is a new name for number | string, a union (one type or the other). An alias can name any type. An interface only describes object shapes, so it cannot name this union.
Building a shape
Line 2 declares the interface Pet: any object with a name that is a string. tsc records that shape. The alias form, type Pet = { name: string }, would mean the same thing here.
Line 3 declares Pet a second time. Interfaces allow that: tsc merges both, so Pet now needs name and age. This is declaration merging. Two type aliases named Pet would be an error: Duplicate identifier 'Pet'.
Line 4 builds Dog on top of Pet with extends and adds id, typed with the alias ID. Dog needs name, age and id. With aliases you would write type Dog = Pet & { id: ID }, an intersection.
Bugs caught
Line 5 makes a Dog but leaves out age. tsc compares the object with Dog's shape and reports: Property 'age' is missing. Run unchecked, JavaScript would quietly print Rex undefined.
You add age: 3 to line 5. tsc checks again: the object has name, age and id, exactly the properties Dog needs, so there are no errors.
Run it
tsc writes JavaScript with lines 1 to 4 gone: aliases and interfaces exist only for the check, so neither costs anything at run time. Node.js runs the two lines left and prints Rex 3.
What happens
;; step 1/8 · why
dog.ts (TypeScript)
> 1 type ID = number | string;
> 2 interface Pet { name: string }
3 interface Pet { age: number }
4 interface Dog extends Pet { id: ID }
5 const d: Dog = { name: "Rex", id: 7 };
6 console.log(d.name, d.age);
type ID = ... a type alias: a new name for a type
interface Pet {...} an interface: a named object shape
The TypeScript Handbook suggests using interface until you need something only an alias can do, such as naming a union. Either works for plain object shapes. The dog.js shown is what tsc 5.9 writes with --target es2022. With no settings tsc 5.9 targets old JavaScript (ES5) and writes var instead of const; the types are removed either way.