104 — Type vs Interface: the Handbook Is Backwards (default to type)
Full companion narrative for I Cannot Believe TypeScript Recommends You Do This — Kyle's case for defaulting to type aliases and reaching for interface only for declaration merging
Video: 104 · I Cannot Believe TypeScript Recommends You Do This! · watch · ~07:44 · Web Dev Simplified (Kyle)
Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path, module 02 (type system) — the sequel to 103: where that lesson’s
filter(Boolean)andJSON.parsefixes are expressed astypealiases, this one argues that should be the default everywhere. Prerequisite for 105, whose predicates can only narrow union types.
the one idea: default to type, not interface
Kyle opens on a split screen — a type UserType and an interface UserInterface side by side — and states his thesis up front: the TypeScript handbook recommends interfaces by default, and he thinks that recommendation is wrong. He rewrites each snippet live in present tense over the editor so the viewer watches the compiler react.
Kyle: “in my opinion, this is completely backwards because interfaces are more complicated than types, they have less features than types.”

declaration syntax: = versus a block
Both shapes consume identically at use sites — the difference lives entirely in the declaration. A type alias binds a name with =, which is why it can name anything; an interface only accepts an object-shaped block.
type UserType = { name: string; age: number };
interface UserInterface {
name: string;
age: number;
}
const a: UserType = { name: "Kyle", age: 30 };
const b: UserInterface = { name: "Kyle", age: 30 };

non-object types are types-only
An interface cannot name a primitive alias. Kyle tries interface SInter = string on screen and shows it is physically impossible — no =, no non-object right-hand side. Anything that is not an object literal shape forces a type, which is the first way an interface-first codebase ends up mixing both constructs anyway.
type SType = string;
const greeting: SType = "hello";
type StringOrNumber = string | number;
const id: StringOrNumber = 123;

unions need types
Kyle builds a union of two object shapes and shows there is no interface spelling of “or”. Defining the two member interfaces is possible, but combining them with | still requires a type alias, so union-heavy domain modeling always routes through type.
type Name = { name: string };
type Age = { age: number };
type NameOrAge = Name | Age;
const v: NameOrAge = { age: 42 };
intersection: & versus extends
Both constructs can combine shapes, and Kyle demonstrates each: & for types, extends for interfaces. The interface form has a sharp edge he hits live — the parent must already be a named type or interface, so inline extension fails until he breaks the parent out into its own declaration.
type Named = { name: string };
type NamedAndAged = Named & { age: number };
interface N {
name: string;
}
interface Person extends N {
age: number;
}

the speed argument is stale
Kyle addresses the claim that interfaces compile faster: it may have been true years ago, but on modern TypeScript the build-time difference is negligible. He rules speed out as a decision criterion — pick on expressiveness, not folklore. Settle it on your own repo instead of restructuring declarations:
npx tsc --noEmit --extendedDiagnostics | grep -E "Total time|Types:"
declaration merging is the one interface-only feature
The single capability types lack: repeat an interface name and the declarations merge. Kyle shows the legitimate use — extending the global Window with a custom property — then warns that the same behavior inside your own codebase is usually an accidental-merge footgun, where a typo’d duplicate silently widens a type instead of erroring like a duplicate type would.
interface Window {
test: string;
}
window.test = "hello";
window.test = 42;
interface User {
name: string;
}
interface User {
age: number;
}


Prev: 103 — Did He Really Fix TypeScript? · Next: 105 — Type Predicates Fix the Extracted-Guard Bug
Watch right after 103: that lesson warns that any leaks in through built-in signatures, and every fix it demonstrates is a type alias — this video makes that the house rule. Pairs forward with 105: predicates narrow union types, and unions are types-only per the sections above, so this video is the prerequisite. Pays off at project scale in 107, where every props object and the sidebar context value are type aliases.
Whisper mistranscriptions corrected for type vs interface. Frame timestamps run ~01:27 (split-screen opener) through ~06:17 (merge demo); the opening frame is blank and the closing frame is talking-head, so screenshots sample frames 2–7.