member-ordering
要求一致的成员声明顺序。
此规则旨在规范类、接口和类型字面量的结构和排序方式。一致的字段、方法和构造函数排序可以使代码更易于阅读、导航和编辑。
此规则已功能冻结:它将不再接收新功能,例如新选项。它仍然会接受其现有功能区域的错误和文档修复。
强制命名和/或排序约定的风格规则往往会随着越来越模糊的功能请求而变得难以理解。此规则已达到 typescript-eslint 项目可以维护的合理范围的极限。有关更多信息,请参阅 eslint-plugin: 功能冻结命名和排序风格规则。
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
};
在游乐场中打开interface Foo {
[Z: string]: any; // -> signature
A(): void; // -> method
new (); // -> constructor
B: string; // -> field
}
在游乐场中打开type Foo = {
// no signature
A(): void; // -> method
// no constructor
B: string; // -> field
};
在游乐场中打开class Foo {
[Z: string]: any; // -> signature
public static A(): void {} // -> method
public B(): void {} // -> method
constructor() {} // -> constructor
private C: string; // -> field
public D: string; // -> field
protected static E: string; // -> field
}
在游乐场中打开const Foo = class {
[Z: string]: any; // -> signature
public static A(): void {} // -> method
public B(): void {} // -> method
constructor() {} // -> constructor
private C: string; // -> field
public D: string; // -> field
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
};
在游乐场中打开class Foo {
public B(): void {} // -> public instance method
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)
}
在游乐场中打开const Foo = class {
public B(): void {} // -> public instance method
private C: string; // (irrelevant)
[Z: string]: any; // (irrelevant)
public D: string; // (irrelevant)
constructor() {} // (irrelevant)
public static A(): void {} // (irrelevant)
public static E: string; // -> public static field
};
在游乐场中打开静态字段在实例字段之前
此配置指定静态字段应在实例字段之前出现,公共静态字段排在最前面。它不适用于接口或类型字面量,因为可访问性和范围不是它们的一部分。
{
"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
};
在游乐场中打开class Foo {
public static A: string; // -> public static field
private static B: string; // -> static field
protected static C: string; // -> static field
private static D: string; // -> static field
private E: string; // -> instance field
[Z: string]: any; // (irrelevant)
}
在游乐场中打开const foo = class {
[Z: string]: any; // -> signature (irrelevant)
public static A: string; // -> public static field
constructor() {} // -> constructor (irrelevant)
private static B: string; // -> static field
protected static C: string; // -> static field
private static D: string; // -> static field
private E: string; // -> instance field
public T(): void {} // -> method (irrelevant)
};
在游乐场中打开类声明
此配置只指定类顺序:方法、构造函数、字段。它不适用于类表达式(对它们使用 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
}
在游乐场中打开class Foo {
public static A(): void {} // -> method
public B(): void {} // -> method
constructor() {} // -> constructor
private C: string; // -> field
public D: string; // -> field
protected static E: string; // -> field
}
在游乐场中打开类表达式
此配置只指定类表达式顺序:方法、构造函数、字段。它不适用于类声明(对它们使用 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
};
在游乐场中打开const foo = class {
public static A(): void {} // -> method
public B(): void {} // -> method
constructor() {} // -> constructor
private C: string; // -> field
public D: string; // -> field
protected static E: string; // -> field
};
在游乐场中打开接口
此配置只指定接口顺序:签名、方法、构造函数、字段。它不适用于类型字面量(对它们使用 typeLiterals
)。默认设置将用于类型字面量和除类表达式以外的所有其他语法构造。
这些成员类型是接口
中唯一允许的类型。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "interfaces": ["signature", "method", "constructor", "field"] },
],
},
}
- ❌ 错误
- ✅ 正确
类型字面量
此配置仅指定类型字面量的顺序:签名、方法、构造函数、字段。它不适用于接口(对它们使用接口
)。默认设置将用于接口和除类表达式之外的所有其他语法结构。
这些成员类型是类型字面量
中唯一允许的类型。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "typeLiterals": ["signature", "method", "constructor", "field"] },
],
},
}
- ❌ 错误
- ✅ 正确
排序选项
在成员组内按字母顺序排序
如果未指定memberTypes
,将应用默认成员顺序。您可以在默认配置中查看默认顺序。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"order": "alphabetically",
},
},
],
},
}
- ❌ 错误
- ✅ 正确
在自定义成员组内按字母顺序排序
此配置指定在每个自定义memberTypes
组内,成员按字母顺序排列(区分大小写)。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"memberTypes": ["method", "field"],
"order": "alphabetically",
},
},
],
},
}
- ❌ 错误
- ✅ 正确
在成员组内不区分大小写地按字母顺序排序
如果未指定memberTypes
,将应用默认成员顺序。您可以在默认配置中查看默认顺序。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"order": "alphabetically-case-insensitive",
},
},
],
},
}
- ❌ 错误
- ✅ 正确
忽略成员组按字母顺序排序
此配置指定所有成员按字母顺序排列(区分大小写)。它通过为memberTypes
指定"never"
来完全忽略任何成员组类型。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{ "default": { "memberTypes": "never", "order": "alphabetically" } },
],
},
}
- ❌ 错误
- ✅ 正确
将可选成员排序到最前面或最后面
optionalityOrder
选项可以用来将所有可选成员放在一个组的开头或结尾。
此配置将所有可选成员放在所有必需成员之前。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"optionalityOrder": "optional-first",
"order": "alphabetically",
},
},
],
},
}
- ❌ 错误
- ✅ 正确
此配置将所有必需成员放在所有可选成员之前。
// .eslintrc.json
{
"rules": {
"@typescript-eslint/member-ordering": [
"error",
{
"default": {
"optionalityOrder": "required-first",
"order": "alphabetically",
},
},
],
},
}
- ❌ 错误
- ✅ 正确
所有支持的选项
成员类型(粒度形式)
有多种方法可以指定成员类型。最明确和粒度化的形式如下所示。
[
// 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 不会对此进行抱怨。
成员组类型(具有可访问性,忽略范围)
还可以根据其可访问性(static
、instance
、abstract
)对成员类型进行分组,忽略其范围。
[
// 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"]
]
成员组类型(具有范围,忽略可访问性)
另一个选项是根据其范围(public
、protected
、private
)对成员类型进行分组,忽略其可访问性。
[
// 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",
]
何时不使用它
如果您不关心成员的一般顺序,则不需要此规则。