Prefer type aliases over interfaces
LOW1.0.0
When to apply Before declaring or reviewing TypeScript object types, or when choosing between type and interface.
Declare types with type by default.
Use interface only when you need declaration merging, such as extending a third-party library's or a global type.
Implementation
- Use
typefor object shapes, unions, and computed types. - Use
interfaceto augment existing declarations, such asNodeJS.ProcessEnvor a library's module types, and disable the lint rule on that line. - A library meant to be extended by consumers may prefer interfaces; choose deliberately.
- Enforce with
@typescript-eslint/consistent-type-definitionsset to'type'.
This is a consistency convention; the two forms are interchangeable for most object types.
Rationale
type can express everything interface can for object shapes, plus unions, mapped types, and conditional types, so one form covers every case.
Using one form consistently removes a decision from every declaration.
Examples
Incorrect (counterexample):
interface UserInfo {
name: string;
role: 'admin' | 'guest';
}
type UserRole = UserInfo['role'];
Correct:
type UserRole = 'admin' | 'guest';
type UserInfo = {
name: string;
role: UserRole;
};
Validation
Run the lint rule, and check that remaining interfaces exist for declaration merging.
An interface that augments a global or library type is not a violation.