Use interface extends for a named object contract you expect to extend, and use a type alias with & when you are composing types as expressions or need a union, tuple, primitive, or other type that an interface cannot represent. The crucial difference is how conflicts behave: extends checks inherited members for compatibility, while an intersection requires a value to satisfy both sides—it does not let one side override the other.
Quick comparison: which should you choose?
| Choose | When it fits | What to watch for |
|---|---|---|
interface Child extends Parent |
You are naming an object-shaped contract or building a clear interface hierarchy. | Incompatible inherited members are rejected when the interface is declared. |
type Combined = A & B |
You want to compose existing types, or need to name a union, tuple, primitive, or other type expression. | Same-name members combine as constraints; incompatible ones can make a property or whole type impossible to satisfy. |
Both forms can describe an object with members from multiple sources when those members are compatible. The TypeScript handbook recommends using interfaces until you need a type feature that aliases provide, then choosing by preference when either form works. See the handbook’s Object Types and Everyday Types.
What happens when properties conflict?
extends checks compatibility up front
An interface that extends another interface must remain compatible with its inherited members. If a child redeclares a property with an incompatible type, TypeScript reports an error at the declaration. That makes extends useful when you want an attempted change to be caught immediately rather than have the resulting contract become unusable.
interface HasId {
id: string;
}
interface NumberId extends HasId {
id: number; // Error: incompatible with the inherited property
}
A child interface can refine an inherited member only when the new declaration is compatible with the inherited contract. It cannot arbitrarily replace the parent’s property type.
#1 Best Overall
& combines constraints; it does not override
An intersection means a value must satisfy both constituent types. If both types declare the same property incompatibly, the property must meet both requirements at once:
type HasStringId = { id: string };
type HasNumberId = { id: number };
type ImpossibleId = HasStringId & HasNumberId;
There is no ordinary value whose id is both a string and a number, so this intersection is not a way to make the right-hand declaration win. With incompatible discriminant properties, TypeScript can reduce the entire intersection to never. The exact edge behavior can depend on the compiler version; the TypeScript 3.9 release notes document stricter intersection assignability checks and discriminant reduction, but they are not a complete matrix for every TypeScript release: TypeScript 3.9 Release Notes.
Rank #2
- TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
- TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
When interface declaration merging matters
Separate declarations with the same interface name can merge into one interface. This is distinct from one interface extending another: merging happens because declarations share a name, and is useful when an API deliberately allows compatible additions, including some library augmentations.
interface RequestOptions {
timeout: number;
}
interface RequestOptions {
retries: number;
}
// RequestOptions now includes timeout and retries.
Non-function members cannot silently replace existing declarations: same-name properties must be compatible, and incompatible declarations produce an error. Type aliases cannot be reopened this way. See the TypeScript handbook’s Declaration Merging reference. Treat merging as an intentional extension point, not as a workaround for a conflicting type.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Use a type alias when the type is more than an object shape
Interfaces are a natural fit for object-like contracts. Type aliases are broader: they can name an object, but also a union, primitive, tuple, intersection, or other type expression. For example, an interface cannot directly express a union of alternatives, while an alias can:
type Result =
| { ok: true; value: string }
| { ok: false; error: Error };
You can also give an intersection a useful name with an alias, such as type AuditedUser = User & AuditFields. A class can implement an object-shaped interface, but its implementation still has to satisfy the interface’s declared contract.
Does one form compile faster?
The TypeScript handbook says interface extension can often be more performant for the compiler than intersection aliases. That is a qualified qualitative observation, not a published benchmark or a guaranteed speedup for every project. Choose the form that accurately expresses the design first; if compiler performance is a concern, measure it in the project and TypeScript version you actually use.
Quick Recap
Best Value
A practical decision process
- Is the type an object contract? Prefer an interface when the name represents a shape that other interfaces should extend.
- Are you combining existing types? Use an intersection when a value genuinely needs to satisfy both constituent types; check for overlapping properties.
- Does the type need to be a union, tuple, primitive, or another type expression? Use a type alias.
- Should declarations be augmentable? Choose an interface only when same-name declaration merging is an intentional part of the API.
- Does correctness depend on a subtle intersection edge case? Check it with the TypeScript version used by the project rather than assuming identical behavior across versions.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




