Type Aliases in TypeScript: type vs. interface
Type Aliases: type vs. interface
~13 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
Besides interface, there's a SECOND way to name a type: the type keyword. This chapter clarifies WHEN each of the two tools is the better choice – one of the most common questions from TypeScript beginners.
The basics of type
type BookStatus = 'available' | 'borrowed' | 'reserved'; // more on this in chapter 9
type ISBN = string; // a simple alias - NOT its own type, just another name for string
type BookSummary = {
title: string;
author: string;
};type can describe object shapes JUST LIKE interface – BookSummary above is functionally almost identical to a same-named interface. BUT: type can ADDITIONALLY do things interface CANNOT, as shown by BookStatus (a union of string literals) or ISBN (an alias for a primitive type).
The three actual differences
// 1. Only interface can be extended via MULTIPLE declarations ("declaration merging"):
interface Config {
name: string;
}
interface Config {
version: string; // gets AUTOMATICALLY added to Config, no error!
}
// Config now has { name: string; version: string }
// 2. type can describe things that are NOT object shapes:
type Num = number;
type Coordinate = [number, number];
type Status = 'active' | 'inactive';
// 3. interface uses 'extends', type uses '&' (intersection, see chapter 9)
interface Base { name: string; }
interface Extended extends Base { extra: string; }
type BaseT = { name: string };
type ExtendedT = BaseT & { extra: string };Achtung: "Declaration merging" (point 1) is usually a SOURCE OF BUGS, not a feature you actively want – two ACCIDENTALLY same-named interfaces merge SILENTLY, instead of showing an error. type behaves "more safely" here: two same-named type declarations are ALWAYS an error ("Duplicate identifier").
This tutorial's practical rule of thumb
interfacefor object shapes describing a "thing" with identity (ourBook,Author,Memberinterfaces from chapter 7) – especially when later extension viaextendsis likely.typefor EVERYTHING else: union types, function types (likeCompareFunctionfrom chapter 6), aliases for primitive types, tuple types.
This rule is a CONVENTION, not a technical necessity – many successful TypeScript projects use exclusively type for EVERYTHING. What matters is CONSISTENCY within a project, not the "perfectly correct" choice in each individual case.
In practice: introducing a more precise book status
Our current isBorrowed: boolean can only represent TWO states – in reality there's also "reserved" (someone's waiting for it). Let's replace the boolean with a more precise type:
import { Author } from './Author.js';
export type BookStatus = 'available' | 'borrowed' | 'reserved';
export interface Book {
readonly isbn: string;
title: string;
author: Author;
publicationYear: number;
pageCount: number;
genres: string[];
status: BookStatus; // replaces the old isBorrowed: boolean
coverImageUrl?: string;
}BookStatus gets explained in detail in chapter 9 (union types) – used here as a practical preview showing WHY type is the better choice than interface for this use case (an interface can't express a value enumeration like this).
Tipp: If you're unsure: start with interface for objects. Once you need something interface CAN'T do (union, tuple, function type), reach for type. That way you never risk choosing "wrong".