'React Typescript HOC TypeError when wrapping a Lazy component

Code:

Link to TypeScript Playground

React version:

"dependencies": {
  "react": "^18.1.0",
  "react-dom": "^18.1.0",
},
"devDependencies": {
  "@types/node": "^17.0.30",
  "@types/react": "^18.0.8",
  "@types/react-dom": "^18.0.3",
  "typescript": "^4.6.4",
}

I'm trying to wrap the lazy component in <React.Suspense> by a HOC to reduce redundant code, but I get a TS Error:

Type 'P' is not assignable to type 'IntrinsicAttributes & (T extends MemoExoticComponent<infer U> | LazyExoticComponent<infer U> ? ReactManagedAttributes<U, ComponentPropsWithRef<T>> : ReactManagedAttributes<...>)'

My HOC code is here:

function lazyLoading<P = {}, T extends ComponentType<P> = ComponentType<P>>(LazyComponent: LazyExoticComponent<T>) {
  return (props: P): JSX.Element => (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent {...props} />
    </Suspense>
  )
}

A simpler version without considering about props:

function lazyLoadingNoProps<T extends ComponentType<any>>(LazyComponent: LazyExoticComponent<T>) {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  )
}

Since I don't want to use LazyExoticComponent<any> (to get rid of any ), I decided to let TS infer the type of lazy component for me.
I've had a look at React.lazy's signature which works perfectly well, I decided to use it on my HOC

export function lazy<T extends ComponentType<any>>(
  factory: () => Promise<{default: T}>
): LazyExoticComponent<T>

And I get the following TS error for this simpler version:

Type '{}' is not assignable to type 'T extends MemoExoticComponent<infer U> | LazyExoticComponent<infer U> ? ReactManagedAttributes<U, ComponentPropsWithRef<T>> : ReactManagedAttributes<...>'

I've totally no idea what's happening here, as the Application is working as expected at runtime, but a TS error here in IDE.


Usage Example (simpler version without props):

const Admin = lazyLoading(lazy(() => import('./pages/Admin')))

const App = (): JSX.Element => (
  <Routes>
    <Route
      path="/admin"
      element={Admin}
    />
  {/* ... */}
)

HOC code is here: Link to TypeScript Playground



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source