跳至主要内容

member-ordering

要求一致的成员声明顺序。

此规则旨在规范类、接口和类型字面量的结构和排序方式。一致的字段、方法和构造函数排序可以使代码更易于阅读、导航和编辑。

注意

此规则已功能冻结:它将不再接收新功能,例如新选项。它仍然会接受其现有功能区域的错误和文档修复。

强制命名和/或排序约定的风格规则往往会随着越来越模糊的功能请求而变得难以理解。此规则已达到 typescript-eslint 项目可以维护的合理范围的极限。有关更多信息,请参阅 eslint-plugin: 功能冻结命名和排序风格规则

.eslintrc.cjs
module.exports = {
"rules": {
"@typescript-eslint/member-ordering": "error"
}
};

在游乐场中尝试此规则 ↗

选项

interface Options {
default?: OrderConfig;
classes?: OrderConfig;
classExpressions?: OrderConfig;
interfaces?: OrderConfig;
typeLiterals?: OrderConfig;
}

type OrderConfig = MemberType[] | SortedOrderConfig | 'never';

interface SortedOrderConfig {
memberTypes?: MemberType[] | 'never';
optionalityOrder?: 'optional-first' | 'required-first';
order?:
| 'alphabetically'
| 'alphabetically-case-insensitive'
| 'as-written'
| 'natural'
| 'natural-case-insensitive';
}

// See below for the more specific MemberType strings
type MemberType = string | string[];

您可以为以下内容配置 OrderConfig 选项

  • default:所有构造(用作回退)
  • classes?: 特别为类覆盖排序
  • classExpressions?: 特别为类表达式覆盖排序
  • interfaces?: 特别为接口覆盖排序
  • typeLiterals?: 特别为类型字面量覆盖排序

每种构造的 OrderConfig 设置最多可以在三个级别上配置排序

  • memberTypes:根据成员类型组进行组织,例如方法与属性
  • optionalityOrder:是否将所有可选成员放在前面或将所有必需成员放在前面
  • order:根据成员名称进行组织,例如按字母顺序

分组

您可以根据成员的不同属性定义许多不同的分组。支持的成员属性按顺序排列如下:

  • 可访问性 ('public' | 'protected' | 'private' | '#private')
  • 装饰 ('decorated'): 成员是否具有显式可访问性装饰器
  • 类型 ('call-signature' | 'constructor' | 'field' | 'readonly-field' | 'get' | 'method' | 'set' | 'signature' | 'readonly-signature')

成员属性可以使用 '-' 连接,以组合成更具体的组。例如,'public-field' 将排在 'private-field' 之前。

排序

order 值指定成员在组内的排序方式。默认值为 as-written,表示任何顺序都可以。其他允许的值为:

  • alphabetically: 按字母顺序排序,直接使用字符串 < 比较(因此 B 排在 a 之前)
  • alphabetically-case-insensitive: 按字母顺序排序,不区分大小写(因此 a 排在 B 之前)
  • natural: 与 alphabetically 相同,但使用 natural-compare-lite 对数字进行更友好的排序
  • natural-case-insensitive: 与 alphabetically-case-insensitive 相同,但使用 natural-compare-lite 对数字进行更友好的排序

默认配置

默认配置如下所示:

{
"default": {
"memberTypes": [
// Index signature
"signature",
"call-signature",

// Fields
"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
"static-initialization",

// Constructors
"public-constructor",
"protected-constructor",
"private-constructor",

"constructor",

// Accessors
"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",

// Getters
"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",

// Setters
"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",

// Methods
"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",
],
},
}
注意

默认配置包含包含其他成员类型的成员组类型。这是为了提供更好的错误消息。

提示

默认情况下,成员不会排序。如果您想按字母顺序排序,则需要提供自定义配置。

示例

所有构造的通用顺序

此配置指定所有构造的顺序。它忽略除签名、方法、构造函数和字段以外的成员类型。它还忽略可访问性和范围。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "default": ["signature", "method", "constructor", "field"] },
],
},
}
interface Foo {
B: string; // -> field

new (); // -> constructor

A(): void; // -> method

[Z: string]: any; // -> signature
}
在游乐场中打开
type Foo = {
B: string; // -> field

// no constructor

A(): void; // -> method

// no signature
};
在游乐场中打开
class Foo {
private C: string; // -> field
public D: string; // -> field
protected static E: string; // -> field

constructor() {} // -> constructor

public static A(): void {} // -> method
public B(): void {} // -> method

[Z: string]: any; // -> signature
}
在游乐场中打开
const Foo = class {
private C: string; // -> field
public D: string; // -> field

constructor() {} // -> constructor

public static A(): void {} // -> method
public B(): void {} // -> method

[Z: string]: any; // -> signature

protected static E: string; // -> field
};
在游乐场中打开

公共实例方法在公共静态字段之前

此配置指定公共实例方法应在公共静态字段之前出现。其他所有内容都可以放置在任何位置。它不适用于接口或类型字面量,因为可访问性和范围不是它们的一部分。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "default": ["public-instance-method", "public-static-field"] },
],
},
}
class Foo {
private C: string; // (irrelevant)

public D: string; // (irrelevant)

public static E: string; // -> public static field

constructor() {} // (irrelevant)

public static A(): void {} // (irrelevant)

[Z: string]: any; // (irrelevant)

public B(): void {} // -> public instance method
}
在游乐场中打开
const Foo = class {
private C: string; // (irrelevant)

[Z: string]: any; // (irrelevant)

public static E: string; // -> public static field

public D: string; // (irrelevant)

constructor() {} // (irrelevant)

public static A(): void {} // (irrelevant)

public B(): void {} // -> public instance method
};
在游乐场中打开

静态字段在实例字段之前

此配置指定静态字段应在实例字段之前出现,公共静态字段排在最前面。它不适用于接口或类型字面量,因为可访问性和范围不是它们的一部分。

{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "default": ["public-static-field", "static-field", "instance-field"] },
],
},
}
class Foo {
private E: string; // -> instance field

private static B: string; // -> static field
protected static C: string; // -> static field
private static D: string; // -> static field

public static A: string; // -> public static field

[Z: string]: any; // (irrelevant)
}
在游乐场中打开
const foo = class {
public T(): void {} // method (irrelevant)

private static B: string; // -> static field

constructor() {} // constructor (irrelevant)

private E: string; // -> instance field

protected static C: string; // -> static field
private static D: string; // -> static field

[Z: string]: any; // signature (irrelevant)

public static A: string; // -> public static field
};
在游乐场中打开

类声明

此配置只指定类顺序:方法、构造函数、字段。它不适用于类表达式(对它们使用 classExpressions)。默认设置将用于类声明和除类声明以外的所有其他语法构造。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "classes": ["method", "constructor", "field"] },
],
},
}
class Foo {
private C: string; // -> field
public D: string; // -> field
protected static E: string; // -> field

constructor() {} // -> constructor

public static A(): void {} // -> method
public B(): void {} // -> method
}
在游乐场中打开

类表达式

此配置只指定类表达式顺序:方法、构造函数、字段。它不适用于类声明(对它们使用 classes)。默认设置将用于类声明和除类表达式以外的所有其他语法构造。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "classExpressions": ["method", "constructor", "field"] },
],
},
}
const foo = class {
private C: string; // -> field
public D: string; // -> field
protected static E: string; // -> field

constructor() {} // -> constructor

public static A(): void {} // -> method
public B(): void {} // -> method
};
在游乐场中打开

接口

此配置只指定接口顺序:签名、方法、构造函数、字段。它不适用于类型字面量(对它们使用 typeLiterals)。默认设置将用于类型字面量和除类表达式以外的所有其他语法构造。

注意

这些成员类型是接口中唯一允许的类型。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "interfaces": ["signature", "method", "constructor", "field"] },
],
},
}
interface Foo {
B: string; // -> field

new (); // -> constructor

A(): void; // -> method

[Z: string]: any; // -> signature
}
在游乐场中打开

类型字面量

此配置仅指定类型字面量的顺序:签名、方法、构造函数、字段。它不适用于接口(对它们使用接口)。默认设置将用于接口和除类表达式之外的所有其他语法结构。

注意

这些成员类型是类型字面量中唯一允许的类型。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "typeLiterals": ["signature", "method", "constructor", "field"] },
],
},
}
type Foo = {
B: string; // -> field

A(): void; // -> method

new (); // -> constructor

[Z: string]: any; // -> signature
};
在游乐场中打开

排序选项

在成员组内按字母顺序排序

如果未指定memberTypes,将应用默认成员顺序。您可以在默认配置中查看默认顺序。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"order": "alphabetically",
},
},
],
},
}
interface Foo {
a: x;
B: x;
c: x;

B(): void;
c(): void;
a(): void;
}
在游乐场中打开

在自定义成员组内按字母顺序排序

此配置指定在每个自定义memberTypes组内,成员按字母顺序排列(区分大小写)。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"memberTypes": ["method", "field"],
"order": "alphabetically",
},
},
],
},
}
interface Foo {
B(): void;
c(): void;
a(): void;

a: x;
B: x;
c: x;
}
在游乐场中打开

在成员组内不区分大小写地按字母顺序排序

如果未指定memberTypes,将应用默认成员顺序。您可以在默认配置中查看默认顺序。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"order": "alphabetically-case-insensitive",
},
},
],
},
}
interface Foo {
B: x;
a: x;
c: x;

B(): void;
c(): void;
a(): void;
}
在游乐场中打开

忽略成员组按字母顺序排序

此配置指定所有成员按字母顺序排列(区分大小写)。它通过为memberTypes指定"never"来完全忽略任何成员组类型。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "default": { "memberTypes": "never", "order": "alphabetically" } },
],
},
}
interface Foo {
b(): void;
a: boolean;

[a: string]: number;
new (): Bar;
(): Baz;
}
在游乐场中打开

将可选成员排序到最前面或最后面

optionalityOrder 选项可以用来将所有可选成员放在一个组的开头或结尾。

此配置将所有可选成员放在所有必需成员之前。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"optionalityOrder": "optional-first",
"order": "alphabetically",
},
},
],
},
}
interface Foo {
a: boolean;
b?: number;
c: string;
}
在游乐场中打开

此配置将所有必需成员放在所有可选成员之前。

// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"optionalityOrder": "required-first",
"order": "alphabetically",
},
},
],
},
}
interface Foo {
a: boolean;
b?: number;
c: string;
}
在游乐场中打开

所有支持的选项

成员类型(粒度形式)

有多种方法可以指定成员类型。最明确和粒度化的形式如下所示。

[
// Index signature
"signature",
"readonly-signature",

// Fields
"public-static-field",
"public-static-readonly-field",
"protected-static-field",
"protected-static-readonly-field",
"private-static-field",
"private-static-readonly-field",
"#private-static-field",
"#private-static-readonly-field",

"public-decorated-field",
"public-decorated-readonly-field",
"protected-decorated-field",
"protected-decorated-readonly-field",
"private-decorated-field",
"private-decorated-readonly-field",

"public-instance-field",
"public-instance-readonly-field",
"protected-instance-field",
"protected-instance-readonly-field",
"private-instance-field",
"private-instance-readonly-field",
"#private-instance-field",
"#private-instance-readonly-field",

"public-abstract-field",
"public-abstract-readonly-field",
"protected-abstract-field",
"protected-abstract-readonly-field",

"public-field",
"public-readonly-field",
"protected-field",
"protected-readonly-field",
"private-field",
"private-readonly-field"
"#private-field",
"#private-readonly-field"

"static-field",
"static-readonly-field",
"instance-field",
"instance-readonly-field"
"abstract-field",
"abstract-readonly-field",

"decorated-field",
"decorated-readonly-field",

"field",
"readonly-field",

// Static initialization
"static-initialization",

// Constructors
"public-constructor",
"protected-constructor",
"private-constructor",

// Getters
"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",

// Setters
"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",

"static-set",
"instance-set",
"abstract-set",

"decorated-set",

"set",

// Methods
"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"
]
注意

如果只指定了一些可能的类型,未指定的类型可以具有任何特定的顺序。这意味着它们可以放在指定的类型之前、之中或之后,并且 linter 不会对此进行抱怨。

成员组类型(具有可访问性,忽略范围)

还可以根据其可访问性(staticinstanceabstract)对成员类型进行分组,忽略其范围。

[
// Index signature
// No accessibility for index signature.

// Fields
"public-field", // = ["public-static-field", "public-instance-field"]
"protected-field", // = ["protected-static-field", "protected-instance-field"]
"private-field", // = ["private-static-field", "private-instance-field"]

// Static initialization
// No accessibility for static initialization.

// Constructors
// Only the accessibility of constructors is configurable. See below.

// Getters
"public-get", // = ["public-static-get", "public-instance-get"]
"protected-get", // = ["protected-static-get", "protected-instance-get"]
"private-get", // = ["private-static-get", "private-instance-get"]

// Setters
"public-set", // = ["public-static-set", "public-instance-set"]
"protected-set", // = ["protected-static-set", "protected-instance-set"]
"private-set", // = ["private-static-set", "private-instance-set"]

// Methods
"public-method", // = ["public-static-method", "public-instance-method"]
"protected-method", // = ["protected-static-method", "protected-instance-method"]
"private-method", // = ["private-static-method", "private-instance-method"]
]

成员组类型(具有可访问性和装饰器)

还可以将带有装饰器的方法或字段分别分组,可以选择指定其可访问性。

[
// Index signature
// No decorators for index signature.

// Fields
"public-decorated-field",
"protected-decorated-field",
"private-decorated-field",

"decorated-field", // = ["public-decorated-field", "protected-decorated-field", "private-decorated-field"]

// Static initialization
// No decorators for static initialization.

// Constructors
// There are no decorators for constructors.

// Getters
"public-decorated-get",
"protected-decorated-get",
"private-decorated-get",

"decorated-get", // = ["public-decorated-get", "protected-decorated-get", "private-decorated-get"]

// Setters
"public-decorated-set",
"protected-decorated-set",
"private-decorated-set",

"decorated-set", // = ["public-decorated-set", "protected-decorated-set", "private-decorated-set"]

// Methods
"public-decorated-method",
"protected-decorated-method",
"private-decorated-method",

"decorated-method", // = ["public-decorated-method", "protected-decorated-method", "private-decorated-method"]
]

成员组类型(具有范围,忽略可访问性)

另一个选项是根据其范围(publicprotectedprivate)对成员类型进行分组,忽略其可访问性。

[
// Index signature
// No scope for index signature.

// Fields
"static-field", // = ["public-static-field", "protected-static-field", "private-static-field"]
"instance-field", // = ["public-instance-field", "protected-instance-field", "private-instance-field"]
"abstract-field", // = ["public-abstract-field", "protected-abstract-field"]

// Static initialization
// No scope for static initialization.

// Constructors
"constructor", // = ["public-constructor", "protected-constructor", "private-constructor"]

// Getters
"static-get", // = ["public-static-get", "protected-static-get", "private-static-get"]
"instance-get", // = ["public-instance-get", "protected-instance-get", "private-instance-get"]
"abstract-get", // = ["public-abstract-get", "protected-abstract-get"]

// Setters
"static-set", // = ["public-static-set", "protected-static-set", "private-static-set"]
"instance-set", // = ["public-instance-set", "protected-instance-set", "private-instance-set"]
"abstract-set", // = ["public-abstract-set", "protected-abstract-set"]

// Methods
"static-method", // = ["public-static-method", "protected-static-method", "private-static-method"]
"instance-method", // = ["public-instance-method", "protected-instance-method", "private-instance-method"]
"abstract-method", // = ["public-abstract-method", "protected-abstract-method"]
]

成员组类型(带作用域和可访问性)

第三种分组选项是忽略作用域和可访问性。

[
// Index signature
// No grouping for index signature.

// Fields
"field", // = ["public-static-field", "protected-static-field", "private-static-field", "public-instance-field", "protected-instance-field", "private-instance-field",
// "public-abstract-field", "protected-abstract-field"]

// Static initialization
// No grouping for static initialization.

// Constructors
// Only the accessibility of constructors is configurable.

// Getters
"get", // = ["public-static-get", "protected-static-get", "private-static-get", "public-instance-get", "protected-instance-get", "private-instance-get",
// "public-abstract-get", "protected-abstract-get"]

// Setters
"set", // = ["public-static-set", "protected-static-set", "private-static-set", "public-instance-set", "protected-instance-set", "private-instance-set",
// "public-abstract-set", "protected-abstract-set"]

// Methods
"method", // = ["public-static-method", "protected-static-method", "private-static-method", "public-instance-method", "protected-instance-method", "private-instance-method",
// "public-abstract-method", "protected-abstract-method"]
]

成员组类型(只读字段)

可以根据字段的readonly修饰符对它们进行分组。

[
// Index signature
"readonly-signature",
"signature",

// Fields
"readonly-field", // = ["public-static-readonly-field", "protected-static-readonly-field", "private-static-readonly-field", "public-instance-readonly-field", "protected-instance-readonly-field", "private-instance-readonly-field", "public-abstract-readonly-field", "protected-abstract-readonly-field"]
"field", // = ["public-static-field", "protected-static-field", "private-static-field", "public-instance-field", "protected-instance-field", "private-instance-field", "public-abstract-field", "protected-abstract-field"]
]

在同一等级分组不同的成员类型

也可以在同一等级分组不同的成员类型。

[
// Index signature
"signature",

// Fields
"field",

// Static initialization
"static-initialization",

// Constructors
"constructor",

// Getters and Setters at the same rank
["get", "set"],

// Methods
"method",
]

何时不使用它

如果您不关心成员的一般顺序,则不需要此规则。

资源