custom lazyload function with typescript

Below is my wish when using lazy loading in React with Typescript, but it looks like bad
I want my code to be as accurate as possible when using typescript (Currently I’m using as and some places don’t make sense). Please help me!!!

import React from "react";

type LazyExportDefault = () => Promise<{ default: React.ComponentType<any> }>;
type ReturnTypeExportLazy = React.LazyExoticComponent<React.ComponentType<any>>;

export function lazyImport<
  T extends React.ComponentType<any>,
  I extends { [K2 in K]: T },
  K extends keyof I
>(factory: () => Promise<I>, name?: K): ReturnTypeExportLazy {
  if (!name) {
    return React.lazy(
      factory as unknown as LazyExportDefault
    ) as ReturnTypeExportLazy;
  }
  return React.lazy(() =>
    factory().then((module) => ({ default: module[name] }))
  );
}
// Usage:
// 1. Exporting declarations: const Home = lazyImport(() => import("./Home"), "Home");
// 2. Default exports: const Home = lazyImport(() => import("./Home"));```


I want my code to be as accurate as possible when using typescript (Currently I'm using as and some places don't make sense). Please help me!!!

Certainly, you can improve the accuracy of your lazy loading code with TypeScript by creating a type-safe function that allows for both named exports and default exports without using any type assertions. You can achieve this by using TypeScript generics and type inference.

Here’s what you can try please:

import React, { ComponentType, LazyExoticComponent } from "react";

type NamedExports<T> = { [key: string]: T };
type LazyExport<T extends ComponentType<any>> = () => Promise<{
  default: T;
}>;

export function lazyImport<T extends ComponentType<any>>(
  factory: LazyExport<T>
): LazyExoticComponent<T>;

export function lazyImport<T extends ComponentType<any>, K extends keyof T>(
  factory: () => Promise<NamedExports<T>>,
  name: K
): LazyExoticComponent<T[K]>;

export function lazyImport(factory: any, name?: any) {
  if (!name) {
    return React.lazy(factory as LazyExport<any>);
  }
  return React.lazy(() =>
    factory().then((module: NamedExports<any>) => ({ default: module[name] }))
  );
}

// Usage:

// For default exports:
const HomeDefault = lazyImport(() => import("./Home"));

// For named exports:
const HomeNamed = lazyImport(() => import("./Home"), "Home");

Do let me know in case you need any further help please! 😄

Leave a Comment