Skip to content

Commit 067d0c6

Browse files
authored
fix: Don't raise TypeScript errors when hydating document (#1304)
1 parent c63b873 commit 067d0c6

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

types/index.d.ts

+53-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// TypeScript Version: 3.8
2-
2+
import * as ReactDOMClient from 'react-dom/client'
33
import {
44
queries,
55
Queries,
@@ -43,10 +43,10 @@ export type RenderResult<
4343
asFragment: () => DocumentFragment
4444
} & {[P in keyof Q]: BoundFunction<Q[P]>}
4545

46-
export interface RenderOptions<
47-
Q extends Queries = typeof queries,
48-
Container extends Element | DocumentFragment = HTMLElement,
49-
BaseElement extends Element | DocumentFragment = Container,
46+
export interface BaseRenderOptions<
47+
Q extends Queries,
48+
Container extends RendererableContainer | HydrateableContainer,
49+
BaseElement extends Element | DocumentFragment,
5050
> {
5151
/**
5252
* By default, React Testing Library will create a div and append that div to the document.body. Your React component will be rendered in the created div. If you provide your own HTMLElement container via this option,
@@ -93,18 +93,64 @@ export interface RenderOptions<
9393
wrapper?: React.JSXElementConstructor<{children: React.ReactNode}>
9494
}
9595

96+
type RendererableContainer = ReactDOMClient.Container
97+
type HydrateableContainer = Parameters<typeof ReactDOMClient['hydrateRoot']>[0]
98+
export interface ClientRenderOptions<
99+
Q extends Queries,
100+
Container extends Element | DocumentFragment,
101+
BaseElement extends Element | DocumentFragment = Container,
102+
> extends BaseRenderOptions<Q, Container, BaseElement> {
103+
/**
104+
* If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side
105+
* rendering and use ReactDOM.hydrate to mount your components.
106+
*
107+
* @see https://testing-library.com/docs/react-testing-library/api/#hydrate)
108+
*/
109+
hydrate?: false | undefined
110+
}
111+
112+
export interface HydrateOptions<
113+
Q extends Queries,
114+
Container extends Element | DocumentFragment,
115+
BaseElement extends Element | DocumentFragment = Container,
116+
> extends BaseRenderOptions<Q, Container, BaseElement> {
117+
/**
118+
* If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side
119+
* rendering and use ReactDOM.hydrate to mount your components.
120+
*
121+
* @see https://testing-library.com/docs/react-testing-library/api/#hydrate)
122+
*/
123+
hydrate: true
124+
}
125+
126+
export type RenderOptions<
127+
Q extends Queries = typeof queries,
128+
Container extends RendererableContainer | HydrateableContainer = HTMLElement,
129+
BaseElement extends Element | DocumentFragment = Container,
130+
> =
131+
| ClientRenderOptions<Q, Container, BaseElement>
132+
| HydrateOptions<Q, Container, BaseElement>
133+
96134
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
97135

98136
/**
99137
* Render into a container which is appended to document.body. It should be used with cleanup.
100138
*/
101139
export function render<
102140
Q extends Queries = typeof queries,
103-
Container extends Element | DocumentFragment = HTMLElement,
141+
Container extends RendererableContainer = HTMLElement,
142+
BaseElement extends Element | DocumentFragment = Container,
143+
>(
144+
ui: React.ReactNode,
145+
options: ClientRenderOptions<Q, Container, BaseElement>,
146+
): RenderResult<Q, Container, BaseElement>
147+
export function render<
148+
Q extends Queries = typeof queries,
149+
Container extends HydrateableContainer = HTMLElement,
104150
BaseElement extends Element | DocumentFragment = Container,
105151
>(
106152
ui: React.ReactNode,
107-
options: RenderOptions<Q, Container, BaseElement>,
153+
options: HydrateOptions<Q, Container, BaseElement>,
108154
): RenderResult<Q, Container, BaseElement>
109155
export function render(
110156
ui: React.ReactNode,

types/test.tsx

+11
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,17 @@ export function testRenderHookProps() {
206206
unmount()
207207
}
208208

209+
export function testContainer() {
210+
render('a', {container: document.createElement('div')})
211+
render('a', {container: document.createDocumentFragment()})
212+
// @ts-expect-error Only allowed in React 19
213+
render('a', {container: document})
214+
render('a', {container: document.createElement('div'), hydrate: true})
215+
// @ts-expect-error Only allowed for createRoot
216+
render('a', {container: document.createDocumentFragment(), hydrate: true})
217+
render('a', {container: document, hydrate: true})
218+
}
219+
209220
/*
210221
eslint
211222
testing-library/prefer-explicit-assert: "off",

0 commit comments

Comments
 (0)