|
| 1 | +# sort-classes |
| 2 | + |
| 3 | +Enforce sorted class members. |
| 4 | + |
| 5 | +Organizing class members in a consistent order improves readability and maintainability. This rule helps developers quickly locate class members and understand the overall structure of the class. |
| 6 | + |
| 7 | +## Config |
| 8 | + |
| 9 | +```ts |
| 10 | +pluginRules: { |
| 11 | + sort-classes: [warn, { type: alphabetical, order: asc, ignoreCase: true }], |
| 12 | +} |
| 13 | +``` |
| 14 | + |
| 15 | +Options: |
| 16 | + |
| 17 | +- `type`: alphabetical | natural | line-length | custom | unsorted (default: alphabetical) |
| 18 | +- `order`: asc | desc (default: asc) |
| 19 | +- `ignoreCase`: boolean (default: true) |
| 20 | +- `specialCharacters`: keep | trim | remove (default: keep) |
| 21 | +- `alphabet`: string (default: ) — only when type=custom |
| 22 | +- `partitionByNewLine`: boolean (default: false) — respect blank-line groups and do not sort across them |
| 23 | + |
| 24 | +Note: This is a heuristic rule; it does not parse full TypeScript syntax trees. |
| 25 | + |
| 26 | +## Example |
| 27 | + |
| 28 | +Before: |
| 29 | + |
| 30 | +```ts |
| 31 | +class User { |
| 32 | + constructor(username: string, email: string, isActive: boolean) { |
| 33 | + this.username = username |
| 34 | + this.email = email |
| 35 | + this.isActive = isActive |
| 36 | + this.roles = [] |
| 37 | + } |
| 38 | + |
| 39 | + addRole(role: string) { |
| 40 | + this.roles.push(role) |
| 41 | + } |
| 42 | + |
| 43 | + deactivate() { |
| 44 | + this.isActive = false |
| 45 | + } |
| 46 | + |
| 47 | + setEmail(newEmail: string) { |
| 48 | + this.email = newEmail |
| 49 | + } |
| 50 | + |
| 51 | + activate() { |
| 52 | + this.isActive = true |
| 53 | + } |
| 54 | + |
| 55 | + removeRole(role: string) { |
| 56 | + this.roles = this.roles.filter(r => r !== role) |
| 57 | + } |
| 58 | + |
| 59 | + getProfile() { |
| 60 | + return { |
| 61 | + username: this.username, |
| 62 | + email: this.email, |
| 63 | + isActive: this.isActive, |
| 64 | + roles: this.roles, |
| 65 | + } |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +After (alphabetical asc): |
| 71 | + |
| 72 | +```ts |
| 73 | +class User { |
| 74 | + activate() { this.isActive = true } |
| 75 | + addRole(role: string) { this.roles.push(role) } |
| 76 | + constructor(username: string, email: string, isActive: boolean) { /* ... */ } |
| 77 | + deactivate() { this.isActive = false } |
| 78 | + getProfile() { /* ... */ } |
| 79 | + removeRole(role: string) { /* ... */ } |
| 80 | + setEmail(newEmail: string) { /* ... */ } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +## Best practices |
| 85 | + |
| 86 | +- Choose `natural` when member names include numeric suffixes (e.g., `step2`, `step10`) |
| 87 | +- Use `partitionByNewLine: true` to preserve intentional manual grouping |
| 88 | +- Keep the rule at `warn` initially to catch problematic cases without blocking |
| 89 | +- Combine with code review guidelines for constructor-first or accessors-first conventions as needed |
0 commit comments