When every class lists its members in the same order, you know where to look: fields at the top, then the constructor, then the methods. Without an agreed order, a field declared between two methods is easy to miss.
By default the order is: index signatures, call signatures, fields, static blocks, constructors, accessor properties, getters, setters, methods. Within each kind, static members come first, then decorated, instance and abstract ones. Within each of those, public comes before protected, private and #private.
A field with a function as its value counts as a method.
Configure
Off by default. To turn it on:
[lint.rules]
"@typescript-eslint/member-ordering" = "error" # or "warn"
Every option, set to its default. The ones that are commented out are unset by default.
[lint.rules]
"@typescript-eslint/member-ordering" = ["error", {
# classes = <"never", list or object>,
# classExpressions = <"never", list or object>,
default = {
memberTypes = [ # list or "never"
"signature",
"call-signature",
"public-static-field",
"protected-static-field",
"private-static-field",
"#private-static-field",
"public-decorated-field",
"protected-decorated-field",
"private-decorated-field",
"public-instance-field",
"protected-instance-field",
"private-instance-field",
"#private-instance-field",
"public-abstract-field",
"protected-abstract-field",
"public-field",
"protected-field",
"private-field",
"#private-field",
"static-field",
"instance-field",
"abstract-field",
"decorated-field",
"field",
"static-initialization",
"public-constructor",
"protected-constructor",
"private-constructor",
"constructor",
"public-static-accessor",
"protected-static-accessor",
"private-static-accessor",
"#private-static-accessor",
"public-decorated-accessor",
"protected-decorated-accessor",
"private-decorated-accessor",
"public-instance-accessor",
"protected-instance-accessor",
"private-instance-accessor",
"#private-instance-accessor",
"public-abstract-accessor",
"protected-abstract-accessor",
"public-accessor",
"protected-accessor",
"private-accessor",
"#private-accessor",
"static-accessor",
"instance-accessor",
"abstract-accessor",
"decorated-accessor",
"accessor",
"public-static-get",
"protected-static-get",
"private-static-get",
"#private-static-get",
"public-decorated-get",
"protected-decorated-get",
"private-decorated-get",
"public-instance-get",
"protected-instance-get",
"private-instance-get",
"#private-instance-get",
"public-abstract-get",
"protected-abstract-get",
"public-get",
"protected-get",
"private-get",
"#private-get",
"static-get",
"instance-get",
"abstract-get",
"decorated-get",
"get",
"public-static-set",
"protected-static-set",
"private-static-set",
"#private-static-set",
"public-decorated-set",
"protected-decorated-set",
"private-decorated-set",
"public-instance-set",
"protected-instance-set",
"private-instance-set",
"#private-instance-set",
"public-abstract-set",
"protected-abstract-set",
"public-set",
"protected-set",
"private-set",
"#private-set",
"static-set",
"instance-set",
"abstract-set",
"decorated-set",
"set",
"public-static-method",
"protected-static-method",
"private-static-method",
"#private-static-method",
"public-decorated-method",
"protected-decorated-method",
"private-decorated-method",
"public-instance-method",
"protected-instance-method",
"private-instance-method",
"#private-instance-method",
"public-abstract-method",
"protected-abstract-method",
"public-method",
"protected-method",
"private-method",
"#private-method",
"static-method",
"instance-method",
"abstract-method",
"decorated-method",
"method",
],
# optionalityOrder = <"optional-first" or "required-first">,
# order = <string>,
},
# interfaces = <"never", list or object>,
# typeLiterals = <"never", list or object>,
}]
Examples
Reported:
class Timer {
start(): void {}
constructor() {}
private elapsed = 0;
}
Not reported:
class Timer {
static readonly limit = 60;
private elapsed = 0;
constructor() {}
get seconds(): number {
return this.elapsed;
}
start(): void {}
stop = (): void => {};
}
Options
The rule takes one object. Each key sets the order for one kind of container.
| Option | What it applies to |
|---|---|
default | Everything that doesn't have its own setting. |
classes | Class declarations. |
classExpressions | Class expressions. |
interfaces | Interfaces. |
typeLiterals | Type literals such as type Point = { ... }. |
Each value is "never" (don't check), a list of member groups, or an object:
| Key | Default | What it does |
|---|---|---|
memberTypes | "never". Under default, the order above | The groups, in the order you want them, or "never" to ignore groups. |
order | "as-written" | How to sort inside a group: "alphabetically", "alphabetically-case-insensitive", "natural", "natural-case-insensitive". |
optionalityOrder | not set | "required-first" or "optional-first". |
A group is a kind of member: signature, readonly-signature, call-signature, field, readonly-field, static-initialization, constructor, accessor, get, set, method. In classes you can narrow it with an accessibility, a scope, or both: private-field, static-method, public-static-method, protected-abstract-get, decorated-field.
- A member goes in the most specific group that's listed.
- A member that doesn't fit any listed group can go anywhere.
- Groups in an inner list have the same rank.
Methods before fields:
class Timer {
start(): void {}
constructor() {}
private elapsed = 0;
}
Only sort by name:
interface Point {
y: number;
x: number;
}
"natural" compares numbers inside names by value, so item2 comes before item10:
interface Row {
item2: string;
item10: string;
}
interface Row {
item2: string;
item10: string;
}
Required members first:
interface User {
nickname?: string;
name: string;
}
Check classes only:
interface Store {
save(): void;
size: number;
}