TypeScript: Interfaces & Custom Types
What you will learn
How to define object shapes with interface, how optional properties work, and how extend lets you compose interfaces.
Defining an interface
Interfaces describe the shape -- the expected properties and their types -- of an object:
interface User {
id: number;
name: string;
email?: string; // optional property (can be absent)
readonly createdAt: Date; // read-only after creation
}
function registerUser(newUser: User): void {
// ...
}
registerUser({ id: 1, name: 'Alice', createdAt: new Date() });
Extending interfaces
interface Animal {
name: string;
speak(): string;
}
interface Dog extends Animal {
breed: string;
}
const myDog: Dog = {
name: 'Rex',
breed: 'German Shepherd',
speak() { return 'Woof!'; }
};
Interface vs Type alias
You can also use type to define shapes:
type Point = {
x: number;
y: number;
};
The main difference: interface can be merged (declared multiple times, TS combines them) and extended. type cannot be reopened but can define primitives and unions.
| Feature | interface |
type |
|---|---|---|
| Can extend | Yes (extends) |
Yes (&) |
| Can be merged | Yes (declaration merging) | No |
| Can define union | No | Yes (string \| number) |
| Can define primitive alias | No | Yes (type ID = string) |
Common mistakes
- Forgetting that interfaces describe minimal requirements -- extra properties cause errors unless you use index signatures
- Leaving required properties uninitialized when creating an object
Quick check below!