Как ссылаться на все возвращаемые типы функций списка для составления react hoc

#javascript #reactjs #typescript #type-inference

Вопрос:

Я хочу создать функцию создания. Он объединяет список компонентов более высокого порядка, а последний параметр — это исходный компонент с реквизитами, который пересекает все возвращаемые типы.

Позвольте мне показать исходный код, потому что мое объяснение немного сбивает с толку (извините за это).

  1. Функция Util для создания специального
 function createHOC<TProps, TInjectedKeys extends keyof TProps>(
  hookFn: (props: any) => Pick<TProps, TInjectedKeys>,
  displayName: string
) {
  return function hoc(Component: React.ComponentType<TProps>) {
    const UiHOC = (props1: Omit<TProps, TInjectedKeys>) => {
      const hookData = hookFn({ ...props1 });

      return <Component {...(props1 as TProps)} {...hookData} />;
    };

    const oriDisplayName = Component.displayName || Component.name || '';
    UiHOC.displayName = `${displayName}(${oriDisplayName})`;

    return UiHOC;
  };
}
 

итак, я создам 2 новых hoc:

 const uiHOC1 = createHOC(() => ({ a: '1' }), 'uiHOC1');
const uiHOC2 = createHOC(() => ({ b: 2, c: false }), 'uiHOC2');
 
  1. Моя функция создания с ссылочным типом
 type HOCType<TProps, TInjectedKeys extends keyof TProps> = (
  Component: React.ComponentType<any>
) => React.ComponentType<Omit<TProps, TInjectedKeys>>;

type PropsType<HOCFns> = HOCFns extends HOCType<infer P, never>[] ? P : never;

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

function compose<Fns extends HOCType<any, any>[]>(
  ...objs: [...Fns]
): (component: React.ComponentType<UnionToIntersection<PropsType<Fns>>>) => any;

function compose(): any {
// ...
}
 
  1. Я хочу получить ссылочный тип в объявлении компонента.
 const ComponentWithHOCs = compose(
  uiHOC1,
  uiHOC2
)((props: I_NEED_REFER_TYPE_HERE) => {
  // It must not be reported typing error here
  return <>{props.a}</>;
});
 

Это работает, но я не уверен, что это правильно. Помогите мне подтвердить или показать мне, если я ошибаюсь.
Вот ссылка на песочницу: https://codesandbox.io/s/intelligent-bush-ezyx6?file=/src/App.tsx
Спасибо