#How to make this util more compact?

3 messages · Page 1 of 1 (latest)

civic fjord
#

Need to make it more compact with full ts support

function compose<Props extends Record<string, unknown>, Ref>(
  ...hocs: Array<
    (
      component: ComponentType<PropsWithoutRef<Props>>
    ) => ComponentType<PropsWithoutRef<Props>>
  >
): (
  component: ComponentType<PropsWithoutRef<Props>>
) => ForwardRefExoticComponent<PropsWithoutRef<Props> & RefAttributes<Ref>> {
  return (component: ComponentType<PropsWithoutRef<Props>>) => {
    const WrappedComponent = forwardRef<Ref, Props>(
      (props, ref: ForwardedRef<Ref>) => {
        const ComposedComponent = hocs.reduceRight(
          (wrapped, hoc) => hoc(wrapped),
          component
        );

        return <ComposedComponent {...props} ref={ref} />;
      }
    );

    WrappedComponent.displayName = `Composed(${
      component.displayName || component.name || 'Component'
    })`;

    return WrappedComponent;
  };
}
quick lintel
#

to start with some of those type annotations aren't necessary because TS can infer them

#

i might write it like this:

const compose =
  <Props, Ref>(
    ...hocs: ((
      component: ComponentType<PropsWithoutRef<Props>>,
    ) => ComponentType<PropsWithoutRef<Props>>)[]
  ) =>
  (
    component: ComponentType<PropsWithoutRef<Props>>,
  ): ForwardRefExoticComponent<PropsWithoutRef<Props> & RefAttributes<Ref>> => {
    const WrappedComponent = forwardRef<Ref, Props>((props, ref) => {
      const ComposedComponent = hocs.reduceRight(
        (wrapped, hoc) => hoc(wrapped),
        component,
      )
      return <ComposedComponent {...props} ref={ref} />
    })

    WrappedComponent.displayName = `Composed(${
      component.displayName || component.name || 'Component'
    })`

    return WrappedComponent
  }