Extending Interfaces
The tracker grows: some tasks repeat every few days, some are shared between people. Each is still a task, with an id and a title, plus something extra. Rather than copying the task fields into every new interface, you extend the original.
The rule
extends inherits every member, then adds its own.
interface Task {
id: number;
title: string;
}
interface RecurringTask extends Task {
everyDays: number;
}
const water: RecurringTask = { id: 3, title: "Water plants", everyDays: 2 };RecurringTask has id, title and everyDays. Because it has everything Task has, a RecurringTask can be passed anywhere a Task is expected.
An interface can extend several interfaces at once, separated by commas:
interface Timestamped { createdAt: string }
interface Shared { ownerIds: number[] }
interface TeamTask extends Task, Timestamped, Shared {
priority: number;
}TeamTask gets all members of all three, plus priority.
Rules for redeclaring a member. An extending interface may repeat a member only with a compatible type — the same type or a narrower one:
interface DoneTask extends Task {
title: "Done"; // fine: a literal is narrower than string
}
interface BadTask extends Task {
id: string; // error: string is not compatible with number
}The compiler reports that BadTask incorrectly extends Task. This protects the promise that every extended type still works as a Task.
An interface can also extend an object type alias, as long as it describes an object shape: interface X extends SomeAlias {...}. That compares with the intersection A & B from the previous section — similar result, but extends reports a clash as an error right at the declaration, while an intersection quietly turns the clashing property into never.
The shortcut
Think of extends as stacking: write the parent's members, then the child's on top. Then check the stack for one conflict: the same name with an incompatible type.
Bottom layer
From Task:
id: number,title: string.
Drills
Answer fast — trust the rule.
How many properties does RecurringTask have if Task has id and title and it adds everyDays?
How do you extend two interfaces at once?
Task has id: number. What happens with interface Bad extends Task { id: string }?
Can a RecurringTask be passed to function show(t: Task)?
Remember
- extends inherits every member, then adds its own.
- Stack the layers, then check for the same name with an incompatible type.
- Trap: redeclaring a member with an unrelated type is an error, not an override.
