Repository: eslint-stylistic/eslint-stylistic
Pull request #796 (2025-05-26 14:08:58)

feat(indent): support `TSTypeAliasDeclaration`
The current `indent` rule does not handle the `TSTypeAliasDeclaration` node, resulting in inconsistent indentation for this syntax.

This PR adds an invalid test case to the `indent._ts_.test.ts` file to demonstrate the issue, and fixes the rule logic to properly indent TSTypeAliasDeclaration nodes.

shixianqin: While fixing this, I also noticed that the same issue occurs with `VariableDeclarator`, `AssignmentExpression`, and `AssignmentPattern` nodes. Is this the intended behavior? If it's a bug, would you prefer that I include the fixes for these cases in this PR as well?

**Invalid examples:**
```ts
// Expected = 2, Actual = 0
let foo =
1

// Expected = 2, Actual = 4
let bar =
    2

// Expected = 2, Actual = 0
foo =
3

// Expected = 2, Actual = 4
foo =
    4

// Expected = 4, Actual = 2
function fn(
  foo =
  5
) {}
pkg-pr-new[bot]: 
[Open in StackBlitz](https://pkg.pr.new/template/12dc256d-9733-4085-b281-ef113945a357)


```
npm i https://pkg.pr.new/@stylistic/eslint-plugin@796
```


```
npm i https://pkg.pr.new/@eslint-stylistic/metadata@796
```


_commit: <a href="https://github.com/eslint-stylistic/eslint-stylistic/runs/44530790209"><code>3a164d9</code></a>_

9romise: The equal operator token in the `VariableDeclarator` nodes are ignored for some reason.
This is the related issue: https://github.com/eslint/eslint/issues/8546.
So we may need to discuss how to fix it compatibly and do it in a new PR.

Patch:
diff --git a/packages/eslint-plugin/rules/indent/indent.ts b/packages/eslint-plugin/rules/indent/indent.ts
index c77a7820..746e539c 100644
--- a/packages/eslint-plugin/rules/indent/indent.ts
+++ b/packages/eslint-plugin/rules/indent/indent.ts
@@ -149,6 +149,7 @@ const KNOWN_NODES = new Set([
   AST_NODE_TYPES.TSRestType,
   AST_NODE_TYPES.TSThisType,
   AST_NODE_TYPES.TSTupleType,
+  AST_NODE_TYPES.TSTypeAliasDeclaration,
   AST_NODE_TYPES.TSTypeAnnotation,
   AST_NODE_TYPES.TSTypeLiteral,
   AST_NODE_TYPES.TSTypeOperator,
@@ -1123,6 +1124,15 @@ export default createRule<RuleOptions, MessageIds>({
 
     const ignoredNodeFirstTokens = new Set<Token>()
 
+    function checkDeclarator(node: Tree.VariableDeclarator | Tree.TSTypeAliasDeclaration, equalOperator: Token) {
+      const tokenAfterOperator = sourceCode.getTokenAfter(equalOperator)!
+
+      offsets.ignoreToken(equalOperator)
+      offsets.ignoreToken(tokenAfterOperator)
+      offsets.setDesiredOffsets([tokenAfterOperator.range[0], node.range[1]], equalOperator, 1)
+      offsets.setDesiredOffset(equalOperator, sourceCode.getLastToken(node.id), 0)
+    }
+
     function checkArrayLikeNode(node: Tree.ArrayExpression | Tree.ArrayPattern | Tree.TSTupleType) {
       const elementList = node.type === AST_NODE_TYPES.TSTupleType ? node.elementTypes : node.elements
       const openingBracket = sourceCode.getFirstToken(node)!
@@ -1815,12 +1825,8 @@ export default createRule<RuleOptions, MessageIds>({
       VariableDeclarator(node) {
         if (node.init) {
           const equalOperator = sourceCode.getTokenBefore(node.init, isNotOpeningParenToken)!
-          const tokenAfterOperator = sourceCode.getTokenAfter(equalOperator)!
 
-          offsets.ignoreToken(equalOperator)
-          offsets.ignoreToken(tokenAfterOperator)
-          offsets.setDesiredOffsets([tokenAfterOperator.range[0], node.range[1]], equalOperator, 1)
-          offsets.setDesiredOffset(equalOperator, sourceCode.getLastToken(node.id), 0)
+          checkDeclarator(node, equalOperator)
         }
       },
 
@@ -1953,6 +1959,12 @@ export default createRule<RuleOptions, MessageIds>({
         checkMemberExpression(node, node.object, node.property)
       },
 
+      TSTypeAliasDeclaration(node) {
+        const equalOperator = sourceCode.getTokenBefore(node.typeAnnotation, isNotOpeningParenToken)!
+
+        checkDeclarator(node, equalOperator)
+      },
+
       'TSTupleType': checkArrayLikeNode,
 
       TSEnumDeclaration(node) {


Test patch:
diff --git a/packages/eslint-plugin/rules/indent/indent._ts_.test.ts b/packages/eslint-plugin/rules/indent/indent._ts_.test.ts
index d364244c..149a704f 100644
--- a/packages/eslint-plugin/rules/indent/indent._ts_.test.ts
+++ b/packages/eslint-plugin/rules/indent/indent._ts_.test.ts
@@ -827,6 +827,13 @@ const map2 = Object.keys(map)
       `,
       options: [2],
     },
+    $`
+      type Foo = string
+      declare type Foo = number
+      namespace Foo {
+          type Bar = boolean
+      }
+    `,
     {
       code: $`
         using a = foo(),
@@ -2115,6 +2122,27 @@ class Foo {
         },
       ],
     },
+    {
+      code: $`
+         type A = number
+          declare type B = number
+        namespace Foo {
+              declare type C = number
+        }
+      `,
+      output: $`
+        type A = number
+        declare type B = number
+        namespace Foo {
+            declare type C = number
+        }
+      `,
+      errors: [
+        { messageId: 'wrongIndentation', data: { expected: '0 spaces', actual: 1 }, line: 1, column: 1 },
+        { messageId: 'wrongIndentation', data: { expected: '0 spaces', actual: 2 }, line: 2, column: 1 },
+        { messageId: 'wrongIndentation', data: { expected: '4 spaces', actual: 6 }, line: 4, column: 1 },
+      ],
+    },
     {
       code: $`
         using a = foo(),