Skip to content

Commit

Permalink
fix: simplify EuiFlexGroup and EuiFlexItem types to make them easier …
Browse files Browse the repository at this point in the history
…to resolve when used with wrappers like `styled()`
  • Loading branch information
tkajtoch committed May 28, 2024
1 parent f2af6f1 commit bea84c0
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 28 deletions.
26 changes: 13 additions & 13 deletions packages/eui/src/components/flex/flex_group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

import React, {
ComponentPropsWithoutRef,
ComponentType,
ElementType,
ForwardedRef,
forwardRef,
FunctionComponent,
PropsWithChildren,
ReactElement,
Ref,
} from 'react';
import classNames from 'classnames';
Expand Down Expand Up @@ -51,9 +52,7 @@ export const DIRECTIONS = [
] as const;
type FlexGroupDirection = (typeof DIRECTIONS)[number];

type ComponentPropType = ElementType<CommonProps>;

export type EuiFlexGroupProps<TComponent extends ComponentPropType = 'div'> =
export type EuiFlexGroupProps<TComponent extends ElementType = 'div'> =
PropsWithChildren &
CommonProps &
ComponentPropsWithoutRef<TComponent> & {
Expand Down Expand Up @@ -83,7 +82,7 @@ export type EuiFlexGroupProps<TComponent extends ComponentPropType = 'div'> =
wrap?: boolean;
};

const EuiFlexGroupInternal = <TComponent extends ComponentPropType>(
const EuiFlexGroupInternal = <TComponent extends ElementType>(
{
className,
component = 'div' as TComponent,
Expand All @@ -96,7 +95,7 @@ const EuiFlexGroupInternal = <TComponent extends ComponentPropType>(
...rest
}: EuiFlexGroupProps<TComponent>,
ref: ForwardedRef<TComponent>
) => {
): ReactElement<EuiFlexGroupProps<TComponent>, TComponent> => {
const styles = useEuiMemoizedStyles(euiFlexGroupStyles);
const cssStyles = [
styles.euiFlexGroup,
Expand All @@ -110,23 +109,24 @@ const EuiFlexGroupInternal = <TComponent extends ComponentPropType>(

const classes = classNames('euiFlexGroup', className);

// Cast the resolved component prop type to ComponentType to help TS
// process multiple infers and the overall type complexity.
// This might not be needed in TypeScript 5
const Component = component as ComponentType<CommonProps & typeof rest>;
// Cast `component` to FunctionComponent to simplify its type.
// Note that FunctionComponent type is used here for purely typing
// convenience since we specify the return type above, and function
// components don't support `ref`s, but that doesn't matter in this case.
const Component = component as FunctionComponent<CommonProps & typeof rest>;

return <Component {...rest} ref={ref} className={classes} css={cssStyles} />;
};

// Cast forwardRef return type to work with the generic TComponent type
// and not fallback to implicit any typing
export const EuiFlexGroup = forwardRef(EuiFlexGroupInternal) as (<
TComponent extends ComponentPropType = 'div',
TComponentRef = ReturnType<typeof EuiFlexGroupInternal>
TComponent extends ElementType = 'div',
TComponentRef = ReactElement<any, TComponent>
>(
props: EuiFlexGroupProps<TComponent> & {
ref?: Ref<TComponentRef>;
}
) => ReturnType<typeof EuiFlexGroupInternal>) & { displayName?: string };
) => ReactElement) & { displayName?: string };

EuiFlexGroup.displayName = 'EuiFlexGroup';
30 changes: 15 additions & 15 deletions packages/eui/src/components/flex/flex_item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import React, {
useEffect,
ComponentPropsWithoutRef,
PropsWithChildren,
ComponentType,
ForwardedRef,
forwardRef,
Ref,
ReactElement,
FunctionComponent,
} from 'react';
import classNames from 'classnames';
import { CommonProps } from '../common';
Expand All @@ -39,9 +40,7 @@ const VALID_GROW_VALUES = [
10,
] as const;

type ComponentPropType = ElementType<CommonProps>;

export type EuiFlexItemProps<TComponent extends ComponentPropType = 'div'> =
export type EuiFlexItemProps<TComponent extends ElementType = 'div'> =
PropsWithChildren &
CommonProps &
ComponentPropsWithoutRef<TComponent> & {
Expand All @@ -53,20 +52,20 @@ export type EuiFlexItemProps<TComponent extends ComponentPropType = 'div'> =
* such as `'div'` or `'span'`, a React component (a function, a class,
* or an exotic component like `memo()`).
*
* `<EuiFlexGroup>` accepts and forwards all extra props to the custom
* `<EuiFlexItem>` accepts and forwards all extra props to the custom
* component.
*
* @example
* // Renders a <button> element
* <EuiFlexItem component="button">
* Submit form
* </EuiFlexGroup>
* </EuiFlexItem>
* @default "div"
*/
component?: TComponent;
};

const EuiFlexItemInternal = <TComponent extends ComponentPropType>(
const EuiFlexItemInternal = <TComponent extends ElementType>(
{
children,
className,
Expand All @@ -75,7 +74,7 @@ const EuiFlexItemInternal = <TComponent extends ComponentPropType>(
...rest
}: EuiFlexItemProps<TComponent>,
ref: ForwardedRef<TComponent>
) => {
): ReactElement<EuiFlexItemProps<TComponent>, TComponent> => {
useEffect(() => {
if (VALID_GROW_VALUES.indexOf(grow) === -1) {
throw new Error(
Expand All @@ -95,10 +94,11 @@ const EuiFlexItemInternal = <TComponent extends ComponentPropType>(

const classes = classNames('euiFlexItem', className);

// Cast the resolved component prop type to ComponentType to help TS
// process multiple infers and the overall type complexity.
// This might not be needed in TypeScript 5
const Component = component as ComponentType<CommonProps & typeof rest>;
// Cast `component` to FunctionComponent to simplify its type.
// Note that FunctionComponent type is used here for purely typing
// convenience since we specify the return type above, and function
// components don't support `ref`s, but that doesn't matter in this case.
const Component = component as FunctionComponent<CommonProps & typeof rest>;

return (
<Component {...rest} ref={ref} css={cssStyles} className={classes}>
Expand All @@ -110,12 +110,12 @@ const EuiFlexItemInternal = <TComponent extends ComponentPropType>(
// Cast forwardRef return type to work with the generic TComponent type
// and not fallback to implicit any typing
export const EuiFlexItem = forwardRef(EuiFlexItemInternal) as (<
TComponent extends ComponentPropType,
TComponentRef = ReturnType<typeof EuiFlexItemInternal>
TComponent extends ElementType,
TComponentRef = ReactElement<any, TComponent>
>(
props: EuiFlexItemProps<TComponent> & {
ref?: Ref<TComponentRef>;
}
) => ReturnType<typeof EuiFlexItemInternal>) & { displayName?: string };
) => ReactElement) & { displayName?: string };

EuiFlexItem.displayName = 'EuiFlexItem';

0 comments on commit bea84c0

Please sign in to comment.