An interface is another way to name an object type:
interface Point {
x: number;
y: number;
}
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
TypeScript only cares about structure: if the value has the right properties, it matches. That is why TypeScript is called a structurally typed system.
Interfaces vs type aliases
For object shapes they are very similar. You can often choose either. The important differences:
interface |
type |
|
|---|---|---|
| Extend | extends |
Intersection (&) |
| Re-open / merge | Yes : declare again to add fields | No : duplicate name errors |
| Unions / primitives | Prefer type |
Great for A | B, renaming primitives |
Extending
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear: Bear = { name: "Winnie", honey: true };
bear.name;
bear.honey;
With a type alias:
type Animal = {
name: string;
};
type Bear = Animal & {
honey: boolean;
};
Declaration merging
Interfaces can be reopened:
interface Window {
title: string;
}
interface Window {
ts: number;
}
// Window now has both title and ts
A type alias cannot do that : a second type Window = ... is an error.
Heuristic
Use interface for object shapes until you need a feature that only type provides (unions, mapped types, renaming a primitive). TypeScript will push you toward the other form when it matters.
interface User {
id: number;
name: string;
email?: string;
}
interface Admin extends User {
permissions: string[];
}
function isAdmin(user: User): user is Admin {
return "permissions" in user;
}
(user is Admin is a type predicate : useful later when narrowing custom types.)
Practice
- Convert an inline
{ x: number; y: number }parameter to aninterface Point. - Extend it to
interface Point3D extends Point { z: number }. - Rewrite the same shapes with
typeand&, and note which form you prefer for your project.