Type vs. Interface¶
Rule¶
It’s called TypeScript not InterfaceScript
- More expressive - Generally more versatile for complex type manipulations.
- Type aliases - Acts as a true alias, capturing the exact shape of a type, while interfaces can be augmented later.
- Union types - Only type allows you to create union types.
- Primitive types - type can represent primitives directly, while interfaces can only describe object shapes
- Tuple types - Only type can define tuples.
- Mapped types - type allows for mapped types that transform existing types.
https://www.youtube.com/watch?v=OSEECveA_0w
Examples¶
🚨 DON’T¶
// Basic object definitions with interface
interface User {
id: number;
name: string;
email: string;
age: number;
}
// Using interface for union-like behavior (impossible)
interface Status {
// Can't do: 'loading' | 'success' | 'error'
value: string;
}
// Interface for primitive types (impossible)
interface UserId {
// Can't alias a primitive directly
value: number;
}
// Interface for tuple types (impossible)
interface Coordinates {
// Can't define [number, number] directly
x: number;
y: number;
}
// Interface for conditional types (impossible)
interface ApiResponse<T> {
// Can't do conditional logic like T extends string ? StringResponse : GenericResponse
data: T;
error?: string;
}
// Interface extending multiple interfaces with conflicts
interface A {
prop: string;
}
interface B {
prop: number;
}
interface Combined extends A, B {
} // Error: conflicting types
✅ DO¶
// Clean object type definitions
type User = {
id: number;
name: string;
email: string;
age: number;
};
// Union types for status/state management
type Status = "loading" | "success" | "error";
// Primitive type aliases
type UserId = number;
// Tuple types for coordinates, pairs, etc.
type Coordinates = [number, number];
// Mapped types for transformations
type ReadonlyUser = {
readonly [K in keyof User]: User[K];
};
// Conditional types
type ApiResult<T> = T extends string ? { message: T } : { data: T };
// Intersection types
type Timestamped = {
createdAt: Date;
updatedAt: Date;
};
type UserWithTimestamp = User & Timestamped;
// Type guard helper type
type TypeGuard<T> = (value: unknown) => value is T;