My-opencode-config typescript-interface-vs-type
Guides when to use interface vs type in TypeScript. Use this skill when defining object types, extending types, or choosing between interface and type aliases.
install
source · Clone the upstream repo
git clone https://github.com/flpbalada/my-opencode-config
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/flpbalada/my-opencode-config "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/typescript-interface-vs-type" ~/.claude/skills/flpbalada-my-opencode-config-typescript-interface-vs-type && rm -rf "$T"
manifest:
skills/typescript-interface-vs-type/SKILL.mdsource content
TypeScript: Interface vs Type
Core Principle
Use
until you need features from interface
.type
This is the official TypeScript recommendation from the TypeScript Handbook.
When to Use Interface
Use
interface for:
- Object type definitions
- Extending other object types
- Class implementations
- Declaration merging (augmenting existing types)
When to Use Type
Use
type only when you need:
- Union types:
type Status = 'pending' | 'approved' | 'rejected' - Mapped types:
type Readonly<T> = { readonly [K in keyof T]: T[K] } - Conditional types:
type NonNullable<T> = T extends null | undefined ? never : T - Tuple types:
type Point = [number, number] - Function types (though interface can also work):
type Handler = (event: Event) => void
Prefer interface extends
Over Intersection (&
)
interface extends&When extending object types, always prefer
interface extends over type intersections.
// Preferred interface User { name: string; } interface Admin extends User { permissions: string[]; } // Avoid type User = { name: string; }; type Admin = User & { permissions: string[]; };
Reason 1: Better Error Messages
With
interface extends, TypeScript raises errors at the definition when extending with incompatible properties:
interface Base { id: number; } // Error immediately at definition interface Extended extends Base { id: string; // Error: Type 'string' is not assignable to type 'number' }
With intersections, errors only appear when accessing the incompatible property, making bugs harder to catch:
type Base = { id: number; }; // No error at definition type Extended = Base & { id: string; }; // Error only when used const item: Extended = { id: 'abc' }; // Error appears here, not at type definition
Reason 2: Better TypeScript Performance
interface extends provides better TypeScript performance:
- Interfaces are cached by name - TypeScript computes the type once and reuses it
- Intersections are recomputed every time they're used, which slows down type checking with complex types
See TypeScript Performance Wiki for details.