Skip to content

fix(react): allow key attribute on components created by with - #1981

Open
geongyu09 wants to merge 2 commits into
toss:mainfrom
geongyu09:fix/with-key-attribute
Open

fix(react): allow key attribute on components created by with#1981
geongyu09 wants to merge 2 commits into
toss:mainfrom
geongyu09:fix/with-key-attribute

Conversation

@geongyu09

Copy link
Copy Markdown

Overview

Suspense.with, ErrorBoundary.with, ErrorBoundaryGroup.with, Delay.with, and ClientOnly.with reject the React-reserved key attribute when the wrapped component takes no props.

const Wrapped = Suspense.with({ fallback: null }, () => <></>)

// ❌ Type 'string' is not assignable to type 'never'.
const list = [<Wrapped key="a" />, <Wrapped key="b" />]

Cause

The TProps type parameter of every with helper defaults to Record<string, never>. Its string index signature makes every attribute — including key — resolve to never, so TypeScript rejects key even though React always accepts it on any element.

Fix

Change the default to Record<never, never>.

It still means "no props" — arbitrary props such as foo="bar" remain a type error — but it has no index signature, so React's own key handling applies again. The same change is applied to all five components for consistency.

- with: <TProps extends ComponentProps<ComponentType> = Record<string, never>>(
+ with: <TProps extends ComponentProps<ComponentType> = Record<never, never>>(

Tests

Added type tests (*.test-d.tsx) for each of the five with helpers covering:

  • key is accepted when the wrapped component has no props
  • arbitrary props are still rejected (@ts-expect-error)
  • key works alongside inferred props

Also added a patch changeset for @suspensive/react.

PR Checklist

  • I did below actions if need
  1. I read the Contributing Guide
  2. I added documents and tests.

@coauthors

coauthors Bot commented Aug 24, 2026

Copy link
Copy Markdown

People can be co-author:

Candidate Reasons Count Add this as commit message
@geongyu09 #1981 1 Co-authored-by: geongyu09 <67491015+geongyu09@users.noreply.github.com>
@codecov-commenter #1981 (comment) 1 Co-authored-by: codecov-commenter <65553080+codecov-commenter@users.noreply.github.com>

@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

@geongyu09 is attempting to deploy a commit to the Toss Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5d341a9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@suspensive/react Patch
@suspensive/codemods Patch
@suspensive/jotai Patch
@suspensive/react-query-4 Patch
@suspensive/react-query-5 Patch
@suspensive/react-query Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.22%. Comparing base (c9ada0a) to head (ab6648c).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1981   +/-   ##
=======================================
  Coverage   93.22%   93.22%           
=======================================
  Files          42       42           
  Lines         664      664           
  Branches      163      164    +1     
=======================================
  Hits          619      619           
  Misses         42       42           
  Partials        3        3           
Components Coverage Δ
@suspensive/react 100.00% <ø> (ø)
@suspensive/react-query 95.83% <ø> (ø)
@suspensive/react-query-4 100.00% <ø> (ø)
@suspensive/react-query-5 100.00% <ø> (ø)
@suspensive/jotai 100.00% <ø> (ø)
@suspensive/codemods 81.60% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused type fix is covered by regression tests, with no unresolved issues.

Pull request overview

Updates React with helpers so prop-less components accept the reserved key attribute while rejecting arbitrary props.

Changes:

  • Updates default prop types across five helpers.
  • Adds compile-time regression tests.
  • Adds a patch changeset for @suspensive/react.
File summaries
File Description
packages/react/src/Suspense.tsx Updates default wrapped-component props.
packages/react/src/Suspense.test-d.tsx Tests Suspense.with typing.
packages/react/src/ErrorBoundaryGroup.tsx Updates default wrapped-component props.
packages/react/src/ErrorBoundaryGroup.test-d.tsx Tests ErrorBoundaryGroup.with typing.
packages/react/src/ErrorBoundary.tsx Updates default wrapped-component props.
packages/react/src/ErrorBoundary.test-d.tsx Tests ErrorBoundary.with typing.
packages/react/src/Delay.tsx Updates default wrapped-component props.
packages/react/src/Delay.test-d.tsx Tests Delay.with typing.
packages/react/src/ClientOnly.tsx Updates default wrapped-component props.
packages/react/src/ClientOnly.test-d.tsx Tests ClientOnly.with typing.
.changeset/fix-with-key-attribute.md Records the patch release.
Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants