hand sketched logo of electrons orbiting a nucleus

TIL: HOC needs ReactNode to be generic

// 1. cant use React.ComponentType else we loose generics
const withStuff = <TProps,>(Component: (props: TProps) => React.ReactNode) => {
  const stuff = useStuff();

  return (props: Omit<TProps, 'stuff'>) => {
    // 2. gotta use `as` here, I know it's annoying
    return <Component {...(props as TProps)} stuff={stuff} />;
  };
};

type MyComponentProps<T> = {
  stuff: Stuff;
  items: T[];
  defaultItem: T;
};

const MyComponent = <T extends React.ReactNode>(props: MyComponentProps<T>) => {
  return (
    <div>
      {props.items.map((item) => (
        <div>{item}</div>
      ))}
    </div>
  );
};

const StuffedComponent = withStuff(MyComponent);

<>
  <StuffedComponent items={[1, 2, 3]} defaultItem={1} />
  {/* 3. defaultItem is inferred to be 1 | 2 | 3 */}
</>;

This is the same trick we used to get nicer forwardRef here.