diff --git a/packages/react-hooks/src/ElementUtils.test.tsx b/packages/react-hooks/src/ElementUtils.test.tsx index 1e18f7a0d7..8c525841e8 100644 --- a/packages/react-hooks/src/ElementUtils.test.tsx +++ b/packages/react-hooks/src/ElementUtils.test.tsx @@ -1,7 +1,12 @@ import { createElement } from 'react'; -import { Text } from '@adobe/react-spectrum'; +import { ItemElement, Item, Text } from '@deephaven/components'; import { isElementOfType } from './ElementUtils'; +beforeEach(() => { + jest.clearAllMocks(); + expect.hasAssertions(); +}); + describe('isElementOfType', () => { function MockComponent() { return null; @@ -21,4 +26,16 @@ describe('isElementOfType', () => { expect(isElementOfType(element, type)).toBe(expected); } ); + + it('should derive the `type` prop', () => { + const element: ItemElement = createElement(Item); + + if (isElementOfType(element, Item)) { + // This is a type check that verifies the type guard narrows this to the + // `Item` function instead of `string | JSXElementConstructor`. This + // proves that #2094 is working as expected. Namely, the compiler will + // complain if it thinks `type` could be a string. + expect(element.type.name).toEqual(Item.name); + } + }); }); diff --git a/packages/react-hooks/src/ElementUtils.ts b/packages/react-hooks/src/ElementUtils.ts index d4dbbca756..ed5cfe4a2f 100644 --- a/packages/react-hooks/src/ElementUtils.ts +++ b/packages/react-hooks/src/ElementUtils.ts @@ -1,4 +1,9 @@ -import { isValidElement, ReactElement, ReactNode } from 'react'; +import { + isValidElement, + JSXElementConstructor, + ReactElement, + ReactNode, +} from 'react'; import { InferComponentProps } from '@deephaven/utils'; /** @@ -7,10 +12,13 @@ import { InferComponentProps } from '@deephaven/utils'; * @param type The type to check against * @returns True if the node is a React element of the specified type */ -export function isElementOfType( - node: ReactNode, - type: T -): node is ReactElement> { +export function isElementOfType< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T extends string | JSXElementConstructor = + | string + // eslint-disable-next-line @typescript-eslint/no-explicit-any + | JSXElementConstructor, +>(node: ReactNode, type: T): node is ReactElement, T> { return isValidElement(node) && node.type === type; }