"interfaceistypefor people who love the wordinterface. Mostly."
What interface does well
interface declares a named object shape. interface User { id: number; name: string } creates a type User with two members. From the consumer's perspective, this is nearly identical to a type alias of the same shape.
The places interface earns its name:
1. extends reads naturally for nominal-feeling hierarchies. interface AdminUser extends User { permissions: string[] } communicates intent the way a class hierarchy does. The equivalent type uses intersection (type AdminUser = User & { permissions: string[] }) which is more powerful but reads less obviously.
2. Declaration merging. Two interface User declarations in the same scope merge into one. This is how libraries augment global types (TypeScript itself does this for lib.dom.d.ts). It's also how you add custom properties to Window, Express.Request, or any third-party interface.
3. Implementing classes. A class can declare class MyUser implements User. Both type and interface work here, but implements reads cleanly with interface and matches the Java/C# muscle memory many developers have.
Declaration merging — the killer feature
This is the unique power of interface. The same name can be declared more than once, and the declarations merge:
interface Box { width: number }
interface Box { height: number }
// Box now has BOTH width and height
It feels weird the first time you see it. The use case becomes obvious when you're augmenting a library's types or extending a global. declare global { interface Window { myApp: MyAppGlobal } } adds myApp to window without you owning the original Window declaration. Type aliases can't do this — they error on duplicate names.
Where interface struggles
Anything that isn't an object shape: unions, intersections of non-objects, mapped types, conditional types, function types in isolation. For all of these, type aliases are the only option. The call-signature syntax for function-shaped interfaces (interface F { (x: number): string }) is technically valid but rarely seen.
interface when you want named, extensible, object-shaped types — especially public API surfaces and types other libraries might augment. Use type for everything else. The two are not in competition; they're tools with overlapping but distinct sweet spots.Pippa's confession
interface declarations mirror them by hand (the Pippa Coop System has a future task to generate them via codegen). I use interface for those request/response shapes because they're hierarchical and read like contracts — exactly what interface is best at. Everything else (unions, derived types, function signatures) is type.