Skip to content

fix: properly type flat config to avoid TypeScript errors#707

Open
everettbu wants to merge 1 commit intomainfrom
fix/eslint-plugin-types
Open

fix: properly type flat config to avoid TypeScript errors#707
everettbu wants to merge 1 commit intomainfrom
fix/eslint-plugin-types

Conversation

@everettbu
Copy link
Copy Markdown

Mirror of facebook/react#36032
Original author: SidWuChou


Bug

When using eslint-plugin-react-hooks with TypeScript strict mode, the following error occurs:

Type 'ReactFlatConfig | undefined' is not assignable to type 'InfiniteArray<ConfigWithExtends>'.
Type 'undefined' is not assignable to type 'InfiniteArray<ConfigWithExtends>'.

Root Cause

The flat config was typed as an empty object {} which caused TypeScript errors when users tried to access pluginReact.configs.flat.recommended.

Fix

This fix properly initializes the flat config type to avoid TypeScript errors.

Test

The change has been tested locally with TypeScript strict mode enabled.

The flat config was typed as empty object {} which caused
TypeScript errors when users tried to access:
  pluginReact.configs.flat.recommended

This fix ensures the type correctly represents the flat config structure.
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR fixes a TypeScript strict-mode error in eslint-plugin-react-hooks by replacing a single type cast on an empty object ({} as { recommended: ...; 'recommended-latest': ... }) with an object literal that declares each flat sub-key explicitly, typed via null as unknown as ReactHooksFlatConfig. The root cause of the original error was that TypeScript inferred the property accesses on the cast empty-object as potentially undefined, which conflicted with the InfiniteArray<ConfigWithExtends> type expected by typescript-eslint flat configs.

Key points:

  • Correct diagnosis and fix: giving TypeScript real object keys at the declaration site eliminates the | undefined widening that caused the error.
  • Safe at runtime: the null placeholders are replaced synchronously by Object.assign(configs.flat, {...}) on lines 89-98, before the module is exported, so no consumer can ever observe null.
  • Style concern: null as unknown as ReactHooksFlatConfig is a double type assertion (escape hatch through unknown) that is slightly stronger than necessary. A single-level {} as ReactHooksFlatConfig per property would achieve the same TypeScript fix with a weaker — and more conventional — assertion, consistent with other casts already present in the file (e.g. basicRuleConfigs).

Confidence Score: 4/5

  • Safe to merge — the fix correctly resolves the TypeScript strict-mode error with no functional regression.
  • The change is minimal and scoped to one file. The TypeScript fix is sound: explicit object keys prevent the | undefined widening. Runtime behaviour is unchanged because Object.assign repopulates the properties synchronously before export. The only deduction is for the use of null as unknown as T (a double type assertion) where a lighter-weight single-level cast would suffice.
  • No files require special attention.

Important Files Changed

Filename Overview
packages/eslint-plugin-react-hooks/src/index.ts Replaces the empty-object type cast ({} as { recommended: ...; 'recommended-latest': ... }) with an object literal that explicitly declares each key initialised to null as unknown as ReactHooksFlatConfig. This gives TypeScript concrete property keys at the declaration site, eliminating the undefined widening that caused the strict-mode error. The runtime null values are replaced synchronously by Object.assign before the module is exported, so consumers are unaffected. Minor concern: the double type assertion (null as unknown as T) is a stronger bypass than necessary.

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/eslint-plugin-react-hooks/src/index.ts
Line: 75-76

Comment:
**Double type assertion hides runtime nullability**

Using `null as unknown as ReactHooksFlatConfig` is a double type assertion (escape hatch through `unknown`) that tells TypeScript these properties are fully-initialized `ReactHooksFlatConfig` objects at all times, while their runtime value is actually `null` until the `Object.assign` call on line 89 replaces them.

In practice this is safe because `Object.assign(configs.flat, {...})` runs synchronously before the module is exported, so no consumer can ever observe the `null` values. However, `null as unknown as T` is a stronger bypass than necessary and entirely suppresses null-safety guarantees from the type system for these properties.

A slightly less aggressive alternative that avoids `null` in the object entirely would be:

```typescript
  flat: {
    recommended: {} as ReactHooksFlatConfig,
    'recommended-latest': {} as ReactHooksFlatConfig,
  },
```

This keeps a plain single-level cast (same pattern used elsewhere in the file for `basicRuleConfigs`) and avoids the runtime `null`, while still giving TypeScript concrete property keys to work with — which is the root cause of the original error.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 1a99db8

Comment on lines +75 to +76
recommended: null as unknown as ReactHooksFlatConfig,
'recommended-latest': null as unknown as ReactHooksFlatConfig,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double type assertion hides runtime nullability

Using null as unknown as ReactHooksFlatConfig is a double type assertion (escape hatch through unknown) that tells TypeScript these properties are fully-initialized ReactHooksFlatConfig objects at all times, while their runtime value is actually null until the Object.assign call on line 89 replaces them.

In practice this is safe because Object.assign(configs.flat, {...}) runs synchronously before the module is exported, so no consumer can ever observe the null values. However, null as unknown as T is a stronger bypass than necessary and entirely suppresses null-safety guarantees from the type system for these properties.

A slightly less aggressive alternative that avoids null in the object entirely would be:

  flat: {
    recommended: {} as ReactHooksFlatConfig,
    'recommended-latest': {} as ReactHooksFlatConfig,
  },

This keeps a plain single-level cast (same pattern used elsewhere in the file for basicRuleConfigs) and avoids the runtime null, while still giving TypeScript concrete property keys to work with — which is the root cause of the original error.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/eslint-plugin-react-hooks/src/index.ts
Line: 75-76

Comment:
**Double type assertion hides runtime nullability**

Using `null as unknown as ReactHooksFlatConfig` is a double type assertion (escape hatch through `unknown`) that tells TypeScript these properties are fully-initialized `ReactHooksFlatConfig` objects at all times, while their runtime value is actually `null` until the `Object.assign` call on line 89 replaces them.

In practice this is safe because `Object.assign(configs.flat, {...})` runs synchronously before the module is exported, so no consumer can ever observe the `null` values. However, `null as unknown as T` is a stronger bypass than necessary and entirely suppresses null-safety guarantees from the type system for these properties.

A slightly less aggressive alternative that avoids `null` in the object entirely would be:

```typescript
  flat: {
    recommended: {} as ReactHooksFlatConfig,
    'recommended-latest': {} as ReactHooksFlatConfig,
  },
```

This keeps a plain single-level cast (same pattern used elsewhere in the file for `basicRuleConfigs`) and avoids the runtime `null`, while still giving TypeScript concrete property keys to work with — which is the root cause of the original error.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant