From aea1dc5b266367426e978090254892e86551f8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 25 Oct 2025 23:02:31 +0200 Subject: [PATCH 1/6] Annotae Grid and List return types explicitly to avoid redundant inlined inferred types --- lib/components/grid/Grid.tsx | 3 ++- lib/components/list/List.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/components/grid/Grid.tsx b/lib/components/grid/Grid.tsx index e0a7d595..0a89483e 100644 --- a/lib/components/grid/Grid.tsx +++ b/lib/components/grid/Grid.tsx @@ -5,6 +5,7 @@ import { useImperativeHandle, useMemo, useState, + type JSX, type ReactNode } from "react"; import { useIsRtl } from "../../core/useIsRtl"; @@ -36,7 +37,7 @@ export function Grid< style, tagName = "div" as TagName, ...rest -}: GridProps) { +}: GridProps): JSX.Element { const cellProps = useMemoizedObject(cellPropsUnstable); const CellComponent = useMemo( () => memo(CellComponentProp, arePropsEqual), diff --git a/lib/components/list/List.tsx b/lib/components/list/List.tsx index 17fecebb..a38b4bb3 100644 --- a/lib/components/list/List.tsx +++ b/lib/components/list/List.tsx @@ -5,6 +5,7 @@ import { useImperativeHandle, useMemo, useState, + type JSX, type ReactNode } from "react"; import { useVirtualizer } from "../../core/useVirtualizer"; @@ -35,7 +36,7 @@ export function List< tagName = "div" as TagName, style, ...rest -}: ListProps) { +}: ListProps): JSX.Element { const rowProps = useMemoizedObject(rowPropsUnstable); const RowComponent = useMemo( () => memo(RowComponentProp, arePropsEqual), From f8f190c7637153ddb90dee19543751a84e5f4f8b Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 26 Oct 2025 16:21:21 -0400 Subject: [PATCH 2/6] Update return type for cellComponent and rowComponent; replace ReactNode with ReactElement --- lib/components/grid/types.ts | 3 ++- lib/components/list/types.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/components/grid/types.ts b/lib/components/grid/types.ts index f2d18643..1d0ca266 100644 --- a/lib/components/grid/types.ts +++ b/lib/components/grid/types.ts @@ -2,6 +2,7 @@ import type { ComponentProps, CSSProperties, HTMLAttributes, + ReactElement, ReactNode, Ref } from "react"; @@ -34,7 +35,7 @@ export type GridProps< rowIndex: number; style: CSSProperties; } & CellProps - ) => ReactNode; + ) => ReactElement; /** * Additional props to be passed to the cell-rendering component. diff --git a/lib/components/list/types.ts b/lib/components/list/types.ts index c47ae2e6..110e759d 100644 --- a/lib/components/list/types.ts +++ b/lib/components/list/types.ts @@ -2,6 +2,7 @@ import type { ComponentProps, CSSProperties, HTMLAttributes, + ReactElement, ReactNode, Ref } from "react"; @@ -98,7 +99,7 @@ export type ListProps< index: number; style: CSSProperties; } & RowProps - ) => ReactNode; + ) => ReactElement; /** * Number of items to be rendered in the list. From 840e2f70020d7dbe36dabb53dd5f4df27659d415 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 26 Oct 2025 16:21:42 -0400 Subject: [PATCH 3/6] Replace List and Grid JSX.Element return type with ReactElement --- lib/components/grid/Grid.tsx | 4 ++-- lib/components/list/List.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/components/grid/Grid.tsx b/lib/components/grid/Grid.tsx index 0a89483e..6b59842f 100644 --- a/lib/components/grid/Grid.tsx +++ b/lib/components/grid/Grid.tsx @@ -5,7 +5,7 @@ import { useImperativeHandle, useMemo, useState, - type JSX, + type ReactElement, type ReactNode } from "react"; import { useIsRtl } from "../../core/useIsRtl"; @@ -37,7 +37,7 @@ export function Grid< style, tagName = "div" as TagName, ...rest -}: GridProps): JSX.Element { +}: GridProps): ReactElement { const cellProps = useMemoizedObject(cellPropsUnstable); const CellComponent = useMemo( () => memo(CellComponentProp, arePropsEqual), diff --git a/lib/components/list/List.tsx b/lib/components/list/List.tsx index a38b4bb3..4f47f6d6 100644 --- a/lib/components/list/List.tsx +++ b/lib/components/list/List.tsx @@ -5,7 +5,7 @@ import { useImperativeHandle, useMemo, useState, - type JSX, + type ReactElement, type ReactNode } from "react"; import { useVirtualizer } from "../../core/useVirtualizer"; @@ -36,7 +36,7 @@ export function List< tagName = "div" as TagName, style, ...rest -}: ListProps): JSX.Element { +}: ListProps): ReactElement { const rowProps = useMemoizedObject(rowPropsUnstable); const RowComponent = useMemo( () => memo(RowComponentProp, arePropsEqual), From 1ea3b1ef2a335e369ccff85b286c950cbbdc03f8 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 26 Oct 2025 16:22:49 -0400 Subject: [PATCH 4/6] Update unit test mock return type --- lib/components/grid/Grid.test.tsx | 2 +- lib/components/list/List.test.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/components/grid/Grid.test.tsx b/lib/components/grid/Grid.test.tsx index 391eb8ea..9c679ae4 100644 --- a/lib/components/grid/Grid.test.tsx +++ b/lib/components/grid/Grid.test.tsx @@ -168,7 +168,7 @@ describe("Grid", () => { /> ); - const NewCellComponent = vi.fn(() => null); + const NewCellComponent = vi.fn(() =>
); rerender( { /> ); - const NewRowComponent = vi.fn(() => null); + const NewRowComponent = vi.fn(() =>
); rerender( Date: Sun, 26 Oct 2025 16:28:55 -0400 Subject: [PATCH 5/6] Udpate generated JSON --- public/generated/js-docs/Grid.json | 2 +- public/generated/js-docs/List.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/generated/js-docs/Grid.json b/public/generated/js-docs/Grid.json index 41533167..ba26d2f5 100644 --- a/public/generated/js-docs/Grid.json +++ b/public/generated/js-docs/Grid.json @@ -28,7 +28,7 @@ }, "cellComponent": { "description": "React component responsible for rendering a cell.

This component will receive an index and style prop by default.\nAdditionally it will receive prop values passed to cellProps.", - "html": "
cellComponent: (props: { ariaAttributes: { \"aria-colindex\": number; role: \"gridcell\"; }; columnIndex: number; rowIndex: number; style: CSSProperties; } & CellProps) => ReactNode
", + "html": "
cellComponent: (props: { ariaAttributes: { \"aria-colindex\": number; role: \"gridcell\"; }; columnIndex: number; rowIndex: number; style: CSSProperties; } & CellProps) => ReactElement<unknown, string | JSXElementConstructor<...>>
", "info": "The prop types for this component are exported as CellComponentProps", "name": "cellComponent", "required": true diff --git a/public/generated/js-docs/List.json b/public/generated/js-docs/List.json index 0050a2c7..e518787b 100644 --- a/public/generated/js-docs/List.json +++ b/public/generated/js-docs/List.json @@ -53,7 +53,7 @@ }, "rowComponent": { "description": "React component responsible for rendering a row.

This component will receive an index and style prop by default.\nAdditionally it will receive prop values passed to rowProps.", - "html": "
rowComponent: (props: { ariaAttributes: { \"aria-posinset\": number; \"aria-setsize\": number; role: \"listitem\"; }; index: number; style: CSSProperties; } & RowProps) => ReactNode
", + "html": "
rowComponent: (props: { ariaAttributes: { \"aria-posinset\": number; \"aria-setsize\": number; role: \"listitem\"; }; index: number; style: CSSProperties; } & RowProps) => ReactElement<unknown, string | JSXElementConstructor<...>>
", "info": "The prop types for this component are exported as RowComponentProps", "name": "rowComponent", "required": true From d51de173ca7542d40ef73b4ce605b243b370fffa Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 26 Oct 2025 16:38:48 -0400 Subject: [PATCH 6/6] Tidy up generated docs --- public/generated/js-docs/Grid.json | 2 +- public/generated/js-docs/List.json | 2 +- scripts/utils/getPropTypeText.ts | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/public/generated/js-docs/Grid.json b/public/generated/js-docs/Grid.json index ba26d2f5..41533167 100644 --- a/public/generated/js-docs/Grid.json +++ b/public/generated/js-docs/Grid.json @@ -28,7 +28,7 @@ }, "cellComponent": { "description": "React component responsible for rendering a cell.

This component will receive an index and style prop by default.\nAdditionally it will receive prop values passed to cellProps.", - "html": "
cellComponent: (props: { ariaAttributes: { \"aria-colindex\": number; role: \"gridcell\"; }; columnIndex: number; rowIndex: number; style: CSSProperties; } & CellProps) => ReactElement<unknown, string | JSXElementConstructor<...>>
", + "html": "
cellComponent: (props: { ariaAttributes: { \"aria-colindex\": number; role: \"gridcell\"; }; columnIndex: number; rowIndex: number; style: CSSProperties; } & CellProps) => ReactNode
", "info": "The prop types for this component are exported as CellComponentProps", "name": "cellComponent", "required": true diff --git a/public/generated/js-docs/List.json b/public/generated/js-docs/List.json index e518787b..0050a2c7 100644 --- a/public/generated/js-docs/List.json +++ b/public/generated/js-docs/List.json @@ -53,7 +53,7 @@ }, "rowComponent": { "description": "React component responsible for rendering a row.

This component will receive an index and style prop by default.\nAdditionally it will receive prop values passed to rowProps.", - "html": "
rowComponent: (props: { ariaAttributes: { \"aria-posinset\": number; \"aria-setsize\": number; role: \"listitem\"; }; index: number; style: CSSProperties; } & RowProps) => ReactElement<unknown, string | JSXElementConstructor<...>>
", + "html": "
rowComponent: (props: { ariaAttributes: { \"aria-posinset\": number; \"aria-setsize\": number; role: \"listitem\"; }; index: number; style: CSSProperties; } & RowProps) => ReactNode
", "info": "The prop types for this component are exported as RowComponentProps", "name": "rowComponent", "required": true diff --git a/scripts/utils/getPropTypeText.ts b/scripts/utils/getPropTypeText.ts index ad2c0860..51ce874e 100644 --- a/scripts/utils/getPropTypeText.ts +++ b/scripts/utils/getPropTypeText.ts @@ -5,6 +5,14 @@ export function getPropTypeText(prop: PropItem) { if (!textToFormat && prop.type.name.includes(":")) { // Edge case where some prop types aren't registered as containing raw TS textToFormat = prop.type.name; + + // List/Grid and rowComponent/cellComponent are annotated with a return type of ReactElement instead of ReactNode + // As a result of this change the generated docs are significantly less readable, so tidy them up here + // See github.com/bvaughn/react-window/issues/875 + textToFormat = textToFormat.replace( + "ReactElement>", + "ReactNode" + ); } if (!textToFormat) {