interface
Declares a named object shape that can extend other types and be reopened to add members.
interface Name<TypeParameters> extends Base1, Base2 {
property: Type;
readonly readonlyProperty: Type;
optionalProperty?: Type;
method(arg: Type): ReturnType;
(arg: Type): ReturnType; // call signature
new (arg: Type): InstanceType; // construct signature
[key: string]: Type; // index signature
}- Added in TypeScript 1.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$Name | identifier | The name the interface is bound to. Two interfaces with the same name in the same scope merge rather than conflict. |
$TypeParametersoptional | <T, U = Default> | Optional generic parameters, which may carry constraints and defaults. |
$extends Base1, Base2optional | heritage clause | Zero or more object types to inherit members from. Unlike a class, an interface may extend several bases at once. |
$members | property | method | call | construct | index signature | The declared shape. Members may be marked readonly or optional with ?. |
Errors
Errors at compile time if two same-named declarations give a member incompatible types, or if the interface tries to extend something that is not a statically known object type.
Changelog
- PHP 4.2Type alias names began appearing in error messages where an expanded anonymous type used to be printed, which removed one of the long-standing readability advantages interfaces had over type aliases.
An interface names the shape of an object: its properties, methods, call and construct signatures, and index signatures. It exists only in the type system and produces no JavaScript.
When to reach for it
The handbook's own heuristic is to use interface until you need something only type can express. Two capabilities make that the default:
- It is open. Declaring the same interface name twice merges the declarations. This is the only way to add members to a type owned by someone else, which is how
@typespackages anddeclare globalpatchWindow,Arrayand third-party classes. extendsis cheaper. The handbook notes that interfaces withextendsare often more performant for the compiler than type aliases combined with intersections, because the result is cached rather than recomputed.
What trips people up
Openness cuts both ways. A second interface User anywhere in the same scope silently adds to the first instead of reporting a duplicate, so a typo in a filename can widen a type you thought was closed. Conflicts are also handled differently from intersections: two interfaces declaring name as string and number is an error, while A & B quietly resolves the property to never.
An interface can only describe object shapes. It cannot alias a primitive, a union or a tuple.
Example
interface Entity {
readonly id: string;
}
interface User extends Entity {
name: string;
email?: string;
}
// Declared again: this MERGES into User above, it does not replace it.
interface User {
lastSeen: number;
}
const u: User = { id: "u_1", name: "Ada", lastSeen: 1700000000 };
console.log(`${u.id} ${u.name} ${u.lastSeen}`);
// u_1 Ada 1700000000When to use it
- Describe the shape of a JSON response before parsing it with a type predicate.
- Define the contract a class must satisfy and check it with an implements clause.
- Add a method to a third-party class from a declaration file via module augmentation.
- Build a public API type that consumers can extend without editing your source.
Frequently asked questions
What is the difference between interface and type in TypeScript?
The practical difference is that interfaces are open and type aliases are closed: declaring the same interface twice merges the members, while declaring the same type alias twice is a duplicate-identifier error. In exchange, a type alias can name anything at all — unions, tuples, primitives, mapped and conditional types — whereas an interface can only describe an object shape.
Can an interface extend a class?
Yes, an interface can extend a class, and it inherits the class's members including private and protected ones. Because those members can only be satisfied by the class or its subclasses, such an interface can effectively only be implemented within that class hierarchy, which is occasionally used deliberately to seal a type.
Why does adding an interface with the same name not cause an error?
Because interfaces participate in declaration merging by design, so same-name declarations combine into one type rather than conflicting. You only get an error when a shared member is declared with incompatible types; identical or non-overlapping members merge silently.
More examples
Extending several interfaces at once
An interface may inherit from any number of bases, which a class cannot do. The output shows that ColorfulCircle carries members from both parents, and that it is still assignable to Circle alone, because assignability in TypeScript is structural rather than nominal.
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
interface ColorfulCircle extends Colorful, Circle {
label?: string;
}
const cc: ColorfulCircle = { color: "red", radius: 42 };
function area(c: Circle): number {
return Math.PI * c.radius ** 2;
}
console.log(cc.color, area(cc).toFixed(2));
// red 5541.77Call, construct and index signatures
An interface describes more than plain properties. Counter types a function object that also has properties, the pattern behind libraries such as jQuery. Registry uses an index signature so any string key is allowed. Note that reg.anythingElse would type as number even though no such key exists at runtime, which is the classic index-signature trap.
interface Counter {
(start: number): string; // callable
interval: number;
reset(): void;
}
interface Registry {
[key: string]: number; // any string key yields a number
}
function makeCounter(): Counter {
const c = ((start: number) => `counting from ${start}`) as Counter;
c.interval = 500;
c.reset = () => { c.interval = 0; };
return c;
}
const counter = makeCounter();
const reg: Registry = { hits: 3, misses: 1 };
console.log(counter(10), counter.interval, reg.hits);
// counting from 10 500 3
Discussion