Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsinterface extends and & both combine object types, but they handle conflicting properties differently. Extending incompatible interfaces is an error at the declaration; an intersection requires a value to satisfy both property types, which can make the property impossible—or reduce the whole type to never when conflicting properties are discriminants. An intersection does not overwrite a property.
How interface extension and intersection handle a conflict
Consider two contracts that give id incompatible types:
interface HasId {
id: string;
}
interface NumericId {
id: number;
}
The outcome depends on how you combine them:
| Composition | When the conflict appears | Meaning of id |
Can a value satisfy it? |
|---|---|---|---|
interface Combined extends HasId, NumericId |
The interface declaration is rejected because the inherited property declarations conflict. | No valid combined interface member is formed. | No; the composition itself is an error. |
type Combined = HasId & NumericId |
The alias can be declared; the conflict matters when using the resulting type. | A value must meet both the string and number requirements. |
For these incompatible primitive types, no ordinary value can satisfy the property. |
The TypeScript Handbook describes conflict handling as the principal difference between these approaches. It says that incompatible same-name properties in an extension produce an error, while intersection properties with different types are merged. Here, “merged” means both constraints apply—not that one type replaces the other. See the TypeScript Handbook: Object Types.
Why an intersection does not mean “the second type wins”
An intersection describes values that belong to both constituent types. It is not object spread, assignment order, or an override operation.
#1 Best Overall
interface HasId {
id: string;
}
interface NumericId {
id: number;
}
type Both = HasId & NumericId;
declare const value: Both;
value.id; // must satisfy both string and number
Writing HasId & NumericId does not make id a number merely because NumericId appears second. Nor does it make it a string. A value of type Both must satisfy both declarations, so a conflicting primitive property leaves no usable value to construct.
If you actually intend to replace a property, express that transformation rather than relying on an intersection. For example, omit the old key and then declare its replacement:
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
type WithNumericId = Omit<HasId, "id"> & {
id: number;
};
This says explicitly that the original id requirement is removed before the replacement is added.
When conflicting discriminants make an intersection never
Some conflicts affect more than one property. A discriminant is commonly a literal-valued property, such as kind, used to tell variants apart. Intersecting two variants that require different values for the same discriminant can collapse the entire type:
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
sideLength: number;
}
type Impossible = Circle & Square;
A value cannot have kind equal to both "circle" and "square". TypeScript 3.9 release notes document that intersections with conflicting discriminant properties can be reduced to never. Once the type is never, property access fails because there is no possible value to access. This release note establishes the behavior for that documented case; it is not a complete version-by-version account of every intersection rule. See the TypeScript 3.9 release notes.
Why extends can error while an intersection can be declared
The two forms make different requests of the compiler. An interface extending other interfaces asks for one coherent interface contract. If inherited members with the same name cannot be reconciled, TypeScript reports the problem at that composition point. That makes the conflict visible when the interface is authored, before code tries to supply a value.
An intersection instead builds a type expression whose values must satisfy every constituent. The alias can be written even when the requirements make a useful value impossible; the consequences appear when code attempts to create, assign, or use such a value. The Handbook cautions that intersections with different property types can have unexpected results when used.
Declaration merging is a related but separate mechanism. The Handbook also documents errors for duplicate non-function interface members with different types during declaration merging, but that rule concerns repeated declarations of the same interface name—not the semantics of extends or &. See TypeScript Handbook: Declaration Merging.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Best Value
Choose based on the contract you mean
- Use
interface extendsto build a named object contract from compatible interfaces, especially when you want an incompatible inherited member rejected at the point of composition. - Use
&when the intended meaning is that a value satisfies all the constraints, or when you need a type expression that is not represented by interface extension. - Inspect overlapping keys before intersecting. For each shared property, ask whether one value can meet both declarations. If not, make the declarations compatible, model the alternatives as a union, or transform the type explicitly—for example, with
Omitfollowed by a replacement property.
These are not interchangeable style choices, and neither syntax is universally preferable. The right one follows from whether you want an interface contract whose inherited members must be coherent, or a type requiring simultaneous satisfaction of every constituent.
For the formal meaning and additional examples of intersections, see the Object Types and Unions and Intersection Types sections of the TypeScript Handbook.
Quick Recap
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.




