@typescript-eslint/member-ordering

Require a consistent order for the members of classes, interfaces and type literals

Also called typescript-eslint/member-ordering, typescript/member-ordering

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:

bunfig.toml
[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.

bunfig.toml
[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#

example.ts2 problems
class Timer {
  start(): void {}

  constructor() {}

  private elapsed = 0;
}
example.tsNo problems
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.

OptionWhat it applies to
defaultEverything that doesn't have its own setting.
classesClass declarations.
classExpressionsClass expressions.
interfacesInterfaces.
typeLiteralsType literals such as type Point = { ... }.

Each value is "never" (don't check), a list of member groups, or an object:

KeyDefaultWhat it does
memberTypes"never". Under default, the order aboveThe 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".
optionalityOrdernot 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:

example.tswith { "default": ["method", "constructor", "field"] }No problems
class Timer {
  start(): void {}

  constructor() {}

  private elapsed = 0;
}

Only sort by name:

example.tswith { "default": { "memberTypes": "never", "order": "alphabetically" } }1 problem
interface Point {
  y: number;
  x: number;
}

"natural" compares numbers inside names by value, so item2 comes before item10:

example.tswith { "default": { "memberTypes": "never", "order": "natural" } }No problems
interface Row {
  item2: string;
  item10: string;
}
example.tswith { "default": { "memberTypes": "never", "order": "alphabetically" } }1 problem
interface Row {
  item2: string;
  item10: string;
}

Required members first:

example.tswith { "default": { "memberTypes": "never", "optionalityOrder": "required-first" } }1 problem
interface User {
  nickname?: string;
  name: string;
}

Check classes only:

example.tswith { "default": "never", "classes": ["field", "method"] }No problems
interface Store {
  save(): void;
  size: number;
}