Fix exhaustive deps bug with flow type casting. (#35691)

Summary:
I noticed there's a bug where the lint will recognize the type on a cast
annotation as a missing dependency;

```
        function MyComponent() {
          type ColumnKey = 'id' | 'name';
          type Item = {id: string, name: string};

          const columns = useMemo(
            () => [
              {
                type: 'text',
                key: 'id',
              } as TextColumn<ColumnKey, Item>,
                              ^^^^^^^^ here
            ],
            [],
          );
        }
```

This is due to the AST of AsExpressions being something like:

AsExpression
  └── typeAnnotation: GenericTypeAnnotation
        └── typeParameters: TypeParameterInstantiation
              └── params[0]: GenericTypeAnnotation
                    └── id: Identifier (name: "ColumnKey")

Where `ColumnKey` never has a TypeParameter Annotation. So we need to
consider it to be a flow type due to it belonging to a
GenericTypeAnnotation

Test Plan:
Added unit tests

Before:
```
Test Suites: 1 failed, 2 passed, 3 total
Tests:       2 failed, 5065 passed, 5067 total
Snapshots:   0 total
Time:        16.517 s
Ran all test suites.
error Command failed with exit code 1.
```

After:
```
 PASS  __tests__/ReactCompilerRuleTypescript-test.ts
 PASS  __tests__/ESLintRulesOfHooks-test.js (6.192 s)
 PASS  __tests__/ESLintRuleExhaustiveDeps-test.js (9.97 s)

Test Suites: 3 passed, 3 total
Tests:       5067 passed, 5067 total
Snapshots:   0 total
Time:        10.21 s, estimated 11 s
Ran all test suites.
  Done in 12.66s.
```
This commit is contained in:
Jorge Cabiedes
2026-02-04 08:24:24 -08:00
committed by GitHub
parent 22a20e1f2f
commit c137dd6f54
2 changed files with 26 additions and 4 deletions

View File

@@ -7913,6 +7913,25 @@ const testsFlow = {
}
`,
},
// Flow type aliases in type assertions should not be flagged as missing dependencies
{
code: normalizeIndent`
function MyComponent() {
type ColumnKey = 'id' | 'name';
type Item = {id: string, name: string};
const columns = useMemo(
() => [
{
type: 'text',
key: 'id',
} as TextColumn<ColumnKey, Item>,
],
[],
);
}
`,
},
],
invalid: [
{

View File

@@ -21,7 +21,7 @@ import type {
VariableDeclarator,
} from 'estree';
import { getAdditionalEffectHooksFromSettings } from '../shared/Utils';
import {getAdditionalEffectHooksFromSettings} from '../shared/Utils';
type DeclaredDependency = {
key: string;
@@ -80,7 +80,6 @@ const rule = {
const rawOptions = context.options && context.options[0];
const settings = context.settings || {};
// Parse the `additionalHooks` regex.
// Use rule-level additionalHooks if provided, otherwise fall back to settings
const additionalHooks =
@@ -565,8 +564,12 @@ const rule = {
continue;
}
// Ignore Flow type parameters
// @ts-expect-error We don't have flow types
if (def.type === 'TypeParameter') {
if (
// @ts-expect-error We don't have flow types
def.type === 'TypeParameter' ||
// @ts-expect-error Flow-specific AST node type
dependencyNode.parent?.type === 'GenericTypeAnnotation'
) {
continue;
}