fix: resolve TS18046 errors for React 19 element props type

React 19 types React.ReactElement props as unknown instead of any. Test
helper functions that access element.props.children, .className, or .href
need explicit props type parameters on React.ReactElement and isValidElement.

Changes:
- admin/PublicShell.test.ts: add WithChildren type, use React.ReactElement<WithChildren>
- dashboard/PublicShell.test.ts: same pattern for childTypes and contentWrapper
- dashboard/StatCard.test.ts: add ElementWithClass type for className access
- dashboard/public-auth-pages.test.ts: add ElementWithHref type for href access

No any, @ts-ignore, or type assertion bypass used.
This commit is contained in:
root
2026-06-28 01:21:36 -04:00
parent 8aab968e09
commit 0c9f3f8635
4 changed files with 16 additions and 8 deletions
@@ -6,7 +6,9 @@ vi.mock('@/components/PublicFooter', () => ({ default: function MockAdminFooter(
import PublicShell from './PublicShell' import PublicShell from './PublicShell'
function childTypes(node: React.ReactElement): string[] { type WithChildren = { children?: React.ReactNode }
function childTypes(node: React.ReactElement<WithChildren>): string[] {
return React.Children.toArray(node.props.children).filter(isValidElement).map((child) => { return React.Children.toArray(node.props.children).filter(isValidElement).map((child) => {
const type = child.type as any const type = child.type as any
if (typeof type === 'string') return type if (typeof type === 'string') return type
@@ -19,10 +19,12 @@ function collectText(node: unknown): string[] {
return []; return [];
} }
type ElementWithHref = { children?: React.ReactNode; href?: string; embedded?: boolean }
function findElement( function findElement(
node: unknown, node: unknown,
predicate: (element: React.ReactElement) => boolean, predicate: (element: React.ReactElement<ElementWithHref>) => boolean,
): React.ReactElement | null { ): React.ReactElement<ElementWithHref> | null {
if (node === null || node === undefined || typeof node === "boolean") if (node === null || node === undefined || typeof node === "boolean")
return null; return null;
if (Array.isArray(node)) { if (Array.isArray(node)) {
@@ -32,7 +34,7 @@ function findElement(
} }
return null; return null;
} }
if (!isValidElement<{ children?: React.ReactNode }>(node)) return null; if (!isValidElement<ElementWithHref>(node)) return null;
if (predicate(node)) return node; if (predicate(node)) return node;
return findElement(node.props.children, predicate); return findElement(node.props.children, predicate);
} }
@@ -6,7 +6,9 @@ vi.mock('@/components/layout/PublicFooter', () => ({ default: function MockPubli
import PublicShell from './PublicShell' import PublicShell from './PublicShell'
function childTypes(node: React.ReactElement): string[] { type WithChildren = { children?: React.ReactNode }
function childTypes(node: React.ReactElement<WithChildren>): string[] {
return React.Children.toArray(node.props.children).filter(isValidElement).map((child) => { return React.Children.toArray(node.props.children).filter(isValidElement).map((child) => {
const type = child.type as any const type = child.type as any
if (typeof type === 'string') return type if (typeof type === 'string') return type
@@ -26,7 +28,7 @@ describe('dashboard PublicShell', () => {
const shell = PublicShell({ embedded: true, children: React.createElement('main', { id: 'content' }) }) const shell = PublicShell({ embedded: true, children: React.createElement('main', { id: 'content' }) })
expect(childTypes(shell)).toEqual(['div']) expect(childTypes(shell)).toEqual(['div'])
const contentWrapper = React.Children.toArray(shell.props.children).find(isValidElement) as React.ReactElement const contentWrapper = React.Children.toArray(shell.props.children).find(isValidElement) as React.ReactElement<WithChildren>
expect(contentWrapper.props.children).toEqual(React.createElement('main', { id: 'content' })) expect(contentWrapper.props.children).toEqual(React.createElement('main', { id: 'content' }))
}) })
}) })
@@ -11,10 +11,12 @@ function collectText(node: unknown): string[] {
return [] return []
} }
function collectElements(node: unknown): React.ReactElement[] { type ElementWithClass = { children?: React.ReactNode; className?: string }
function collectElements(node: unknown): React.ReactElement<ElementWithClass>[] {
if (node === null || node === undefined || typeof node === 'boolean') return [] if (node === null || node === undefined || typeof node === 'boolean') return []
if (Array.isArray(node)) return node.flatMap(collectElements) if (Array.isArray(node)) return node.flatMap(collectElements)
if (!isValidElement<{ children?: React.ReactNode }>(node)) return [] if (!isValidElement<ElementWithClass>(node)) return []
return [node, ...collectElements(node.props.children)] return [node, ...collectElements(node.props.children)]
} }