From 4733a943fd0b9c63ae44a89a9a871db297faa5ef Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 15 Oct 2025 09:33:21 +0000
Subject: [PATCH 1/2] Initial plan
From ce99eb8c01d0d0914ba8074c695c31bf15e0a30c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 15 Oct 2025 09:45:16 +0000
Subject: [PATCH 2/2] Add errorBoundaryProps utility function
Co-authored-by: manudeli <61593290+manudeli@users.noreply.github.com>
---
packages/react/src/ErrorBoundary.spec.tsx | 73 +++++++++++++++++++
packages/react/src/ErrorBoundary.test-d.tsx | 80 +++++++++++++++++++++
packages/react/src/ErrorBoundary.tsx | 20 ++++++
packages/react/src/index.ts | 2 +-
4 files changed, 174 insertions(+), 1 deletion(-)
diff --git a/packages/react/src/ErrorBoundary.spec.tsx b/packages/react/src/ErrorBoundary.spec.tsx
index 3ea52a297..b0738ee10 100644
--- a/packages/react/src/ErrorBoundary.spec.tsx
+++ b/packages/react/src/ErrorBoundary.spec.tsx
@@ -5,6 +5,7 @@ import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary'
import {
ErrorBoundary,
type ErrorBoundaryFallbackProps,
+ errorBoundaryProps,
useErrorBoundary,
useErrorBoundaryFallbackProps,
} from './ErrorBoundary'
@@ -621,3 +622,75 @@ describe('ErrorBoundary.with', () => {
expect(ErrorBoundary.with({ fallback: () => <>> }, () => <>>).displayName).toBe('ErrorBoundary.with(Component)')
})
})
+
+describe('errorBoundaryProps', () => {
+ beforeEach(() => vi.useFakeTimers())
+
+ afterEach(() => {
+ vi.useRealTimers()
+ Throw.reset()
+ })
+
+ it('should return the props object passed to it', () => {
+ const props = errorBoundaryProps({
+ fallback:
Error
,
+ onError: vi.fn(),
+ onReset: vi.fn(),
+ })
+
+ expect(props).toEqual({
+ fallback: Error
,
+ onError: expect.any(Function),
+ onReset: expect.any(Function),
+ })
+ })
+
+ it('should work with function fallback', () => {
+ const fallbackComponent = ({ error }: ErrorBoundaryFallbackProps) => {error.message}
+ const props = errorBoundaryProps({
+ fallback: fallbackComponent,
+ })
+
+ expect(props.fallback).toBe(fallbackComponent)
+ })
+
+ it('should preserve type inference for shouldCatch', () => {
+ const props = errorBoundaryProps({
+ fallback: Error
,
+ shouldCatch: CustomError,
+ })
+
+ expect(props.shouldCatch).toBe(CustomError)
+ })
+
+ it('should work with resetKeys', () => {
+ const resetKeys = ['key1', 'key2']
+ const props = errorBoundaryProps({
+ fallback: Error
,
+ resetKeys,
+ })
+
+ expect(props.resetKeys).toEqual(resetKeys)
+ })
+
+ it('should integrate with ErrorBoundary component', async () => {
+ const onError = vi.fn()
+ const props = errorBoundaryProps({
+ fallback: (props) => <>{props.error.message}>,
+ onError,
+ })
+
+ render(
+
+
+ {TEXT}
+
+
+ )
+
+ expect(screen.queryByText(TEXT)).toBeInTheDocument()
+ await act(() => vi.advanceTimersByTime(100))
+ expect(screen.queryByText(ERROR_MESSAGE)).toBeInTheDocument()
+ expect(onError).toHaveBeenCalledTimes(1)
+ })
+})
diff --git a/packages/react/src/ErrorBoundary.test-d.tsx b/packages/react/src/ErrorBoundary.test-d.tsx
index c7b623110..bb853e76f 100644
--- a/packages/react/src/ErrorBoundary.test-d.tsx
+++ b/packages/react/src/ErrorBoundary.test-d.tsx
@@ -1231,3 +1231,83 @@ describe('', () => {
})
})
})
+
+describe('errorBoundaryProps', () => {
+ it('should return props with correct types', () => {
+ const { errorBoundaryProps } = require('./ErrorBoundary')
+
+ const props = errorBoundaryProps({
+ fallback: Error
,
+ })
+
+ expectTypeOf(props).toMatchTypeOf<{
+ fallback: ReactNode
+ }>()
+ })
+
+ it('should preserve type inference for shouldCatch with CustomError', () => {
+ const { errorBoundaryProps } = require('./ErrorBoundary')
+
+ const props = errorBoundaryProps({
+ fallback: ({ error }: { error: CustomError; reset: () => void }) => {error.message}
,
+ shouldCatch: CustomError,
+ })
+
+ expectTypeOf(props).toMatchTypeOf<{
+ fallback: ReactNode
+ shouldCatch?: typeof CustomError
+ }>()
+ })
+
+ it('should work with function fallback that has typed error', () => {
+ const { errorBoundaryProps } = require('./ErrorBoundary')
+
+ const props = errorBoundaryProps({
+ fallback: ({ error, reset }: { error: CustomError; reset: () => void }) => (
+
+ {error.message}
+
+
+ ),
+ shouldCatch: CustomError,
+ })
+
+ expectTypeOf(props.fallback).toMatchTypeOf<
+ ReactNode | ((props: { error: CustomError; reset: () => void }) => ReactNode)
+ >()
+ })
+
+ it('should accept all ErrorBoundary props except children', () => {
+ const { errorBoundaryProps } = require('./ErrorBoundary')
+
+ const props = errorBoundaryProps({
+ fallback: Error
,
+ resetKeys: ['key1', 'key2'],
+ onError: (error: CustomError) => console.error(error),
+ onReset: () => console.log('reset'),
+ shouldCatch: CustomError,
+ })
+
+ expectTypeOf(props).toMatchTypeOf<{
+ fallback: ReactNode
+ resetKeys?: unknown[]
+ onError?: (error: CustomError, info: unknown) => void
+ onReset?: () => void
+ shouldCatch?: typeof CustomError
+ }>()
+ })
+
+ it('should work with array of error matchers', () => {
+ const { errorBoundaryProps } = require('./ErrorBoundary')
+
+ const props = errorBoundaryProps({
+ fallback: ({ error }: { error: Error; reset: () => void }) => {error.message}
,
+ shouldCatch: [CustomError, (error: Error) => error instanceof Error],
+ })
+
+ expectTypeOf(props).toMatchTypeOf<{
+ fallback: ReactNode
+ shouldCatch?: [typeof CustomError, (error: Error) => boolean]
+ }>()
+ })
+})
diff --git a/packages/react/src/ErrorBoundary.tsx b/packages/react/src/ErrorBoundary.tsx
index a93683c9f..33d1b4f08 100644
--- a/packages/react/src/ErrorBoundary.tsx
+++ b/packages/react/src/ErrorBoundary.tsx
@@ -319,3 +319,23 @@ export const useErrorBoundaryFallbackProps = (): E
[errorBoundary.error, errorBoundary.reset]
)
}
+
+/**
+ * This utility function is a helper for creating ErrorBoundary props with proper type inference.
+ * It simply returns the props object passed to it, but helps with type inference.
+ * @see {@link https://suspensive.org/docs/react/ErrorBoundary Suspensive Docs}
+ * @example
+ * ```tsx
+ * const errorBoundary = errorBoundaryProps({
+ * fallback: ({ error }) => {error.message}
,
+ * onError: (error) => console.error(error),
+ * })
+ *
+ *
+ *
+ *
+ * ```
+ */
+export const errorBoundaryProps = (
+ props: PropsWithoutChildren>
+) => props
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index f391000b4..cf1f51ff3 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -1,7 +1,7 @@
export { ClientOnly } from './ClientOnly'
export { DefaultPropsProvider, DefaultProps } from './DefaultProps'
export { Delay } from './Delay'
-export { ErrorBoundary, useErrorBoundary, useErrorBoundaryFallbackProps } from './ErrorBoundary'
+export { ErrorBoundary, useErrorBoundary, useErrorBoundaryFallbackProps, errorBoundaryProps } from './ErrorBoundary'
export { ErrorBoundaryGroup, useErrorBoundaryGroup } from './ErrorBoundaryGroup'
export { lazy, reloadOnError, createLazy } from './lazy'
export { Suspense } from './Suspense'