nextjs - 💡(How to fix) Fix SWC 56 skips React Compiler for .ts files with bare generic arrow functions [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#91791Fetched 2026-04-08 01:16:17
View on GitHub
Comments
1
Participants
2
Timeline
8
Reactions
0
Timeline (top)
labeled ×4closed ×1commented ×1locked ×1

Fix Action

Workaround

Use <T,> (trailing comma) or <T = unknown> to disambiguate the generic from JSX for SWC's parser.

Note: formatters like oxfmt strip the trailing comma in .ts files (oxc-project/oxc#18924), so // oxfmt-ignore or // prettier-ignore may be needed.

Code Example

// app/useMyHook.ts
import { useState } from 'react';

const useMyHook = <T>(initialValue: T) => {
  const [value, setValue] = useState(initialValue);
  return { setValue, value };
};

export default useMyHook;

---

Operating System: macOS (darwin arm64)
Next.js: 16.2.1 (broken), 16.2.0-canary.41 (working)
React: 19.2.4
babel-plugin-react-compiler: 1.0.0
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/bixente4669/next-compiler-repro

To Reproduce

  1. Create a .ts file with a generic arrow function using bare <T> (no trailing comma, no default):
// app/useMyHook.ts
import { useState } from 'react';

const useMyHook = <T>(initialValue: T) => {
  const [value, setValue] = useState(initialValue);
  return { setValue, value };
};

export default useMyHook;
  1. Enable React Compiler: reactCompiler: true in next.config.mjs
  2. bun dev, open the page, inspect .next/dev/static/chunks/ for the chunk containing useMyHook

Result: useMyHook is NOT compiled — useState is called directly, no compiler-runtime import, no memo cache.

Expected: The hook should be compiled. Adding <T,> (trailing comma) or <T = unknown> fixes it.

Current vs. Expected behavior

Current: SWC 56's isReactCompilerRequired() misidentifies bare <T> in .ts files (likely parsing it as JSX), causing the entire file to be skipped from React Compiler processing. All hooks in the file silently lose memoization.

Expected: .ts files should not have JSX ambiguity — <T> can only be a generic type parameter. The compiler should process these files normally.

Provide environment information

Operating System: macOS (darwin arm64)
Next.js: 16.2.1 (broken), 16.2.0-canary.41 (working)
React: 19.2.4
babel-plugin-react-compiler: 1.0.0

Which area(s) are affected? (Select all that apply)

SWC, React Compiler

Bisect results

VersionCompiled?
16.2.0-canary.41 (SWC 55)✅ Yes
16.2.0-canary.42 (SWC 56)No (first bad)
16.2.1❌ No

Introduced by commit 1fac9a1 — "Upgrade to swc 56" (PR #89111).

Workaround

Use <T,> (trailing comma) or <T = unknown> to disambiguate the generic from JSX for SWC's parser.

Note: formatters like oxfmt strip the trailing comma in .ts files (oxc-project/oxc#18924), so // oxfmt-ignore or // prettier-ignore may be needed.

extent analysis

Fix Plan

To fix the issue, you can modify your generic arrow function to include a trailing comma or a default type. Here are the steps:

  • Modify the useMyHook function to include a trailing comma:
const useMyHook = <T,>(initialValue: T) => {
  const [value, setValue] = useState(initialValue);
  return { setValue, value };
};
  • Alternatively, you can specify a default type for the generic type parameter:
const useMyHook = <T = unknown>(initialValue: T) => {
  const [value, setValue] = useState(initialValue);
  return { setValue, value };
};
  • If you are using a formatter like oxfmt, you may need to add an ignore comment to prevent the trailing comma from being stripped:
// oxfmt-ignore
const useMyHook = <T,>(initialValue: T) => {
  const [value, setValue] = useState(initialValue);
  return { setValue, value };
};

Verification

To verify that the fix worked, you can check the compiled chunk in .next/dev/static/chunks/ for the presence of the compiler-runtime import and memo cache.

Extra Tips

  • Be aware of the potential for formatters to strip trailing commas in .ts files.
  • Consider using a default type for generic type parameters to avoid ambiguity.
  • If you are using an older version of SWC, you may need to upgrade to a version that correctly handles generic type parameters in .ts files.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING