Skip to main content

Type vs Interface: My Rule

Default to type. Use interface when you need declaration merging or a library-style API.

That's it. Everything else is noise.


Why I default to type

Works for primitives, unions, tuples — things interface can't do:

type ID = string | number;
type Status = 'active' | 'inactive';
type UserOrAdmin = User | Admin;

When I use interface

Declaration merging — extending types defined elsewhere (e.g. third-party library augmentation):

// Extend Express Request globally
interface Request {
user?: User;
}

Class contractsimplements reads more naturally with interface:

interface Serializable {
serialize(): string;
}
class Config implements Serializable { ... }

Quick comparison

typeinterface
Primitives / unionsYesNo
Declaration mergingNoYes
ExtendingVia & intersectionNative extends
implements (class)WorksWorks

Decision flowchart


Bottom line

If you're unsure: use type. You can always change it later.


Reference