Búsqueda de sitios web

No se pueden importar exportaciones nombradas de una biblioteca NPM externa con TypeScript


No puedo importar exportaciones con nombre desde una biblioteca de componentes externa que he creado tal como se describe en la documentación oficial. La situación parece ser muy específica ya que me cuesta encontrar algo en línea que me acerque a la solución. ¿Alguien logró hacerlo funcionar?

Aquí viene el contexto...

En mi biblioteca NPM

Componente

Componente modal (fragmento)

const Modal: React.FC<ModalProps> = ({ onCancelCallback, children }) => {...};
export default Modal;

Como puedes ver, lo exporto como predeterminado desde Modal.tsx, pero luego lo reexporto como una exportación con nombre en el archivo index.ts de cada carpeta de la siguiente manera:

export { default as Modal } from './Modal';

entonces

export { Modal } from './Modal';

y, finalmente:

export * from './components';

Interfaz

PropiedadesDelModal

export interface ModalProps {
  onCancelCallback?: () => void;
}

En Next.js

Aquí está cómo estoy importando mi componente externo "Modal" en uno de los componentes de Next.js (no páginas):

nextjscomponent.tsx

import dynamic from 'next/dynamic';
const Modal = dynamic(() => import('my-ui-kit').then((mod) => mod.Modal), {
  ssr: false,
});

Error de TypeScript

Argument of type '() => Promise<React.ComponentClass<never, any> | React.FunctionComponent<never> | { default: React.ComponentType<never>; } | React.FC<ModalProps>>' is not assignable to parameter of type 'DynamicOptions<{}> | (() => LoaderComponent<{}>) | LoaderComponent<{}>'.
  Type '() => Promise<React.ComponentClass<never, any> | React.FunctionComponent<never> | { default: React.ComponentType<never>; } | React.FC<ModalProps>>' is not assignable to type '() => LoaderComponent<{}>'.
    Type 'Promise<ComponentClass<never, any> | FunctionComponent<never> | { default: ComponentType<never>; } | FC<ModalProps>>' is not assignable to type 'LoaderComponent<{}>'.
      Type 'ComponentClass<never, any> | FunctionComponent<never> | { default: ComponentType<never>; } | FC<ModalProps>' is not assignable to type 'ComponentClass<{}, any> | FunctionComponent<{}> | { default: ComponentType<{}>; }'.
        Type 'ComponentClass<never, any>' is not assignable to type 'ComponentClass<{}, any> | FunctionComponent<{}> | { default: ComponentType<{}>; }'.
          Type 'ComponentClass<never, any>' is not assignable to type 'ComponentClass<{}, any>'.
            Types of property 'getDerivedStateFromProps' are incompatible.
              Type 'GetDerivedStateFromProps<never, any> | undefined' is not assignable to type 'GetDerivedStateFromProps<{}, any> | undefined'.
                Type 'GetDerivedStateFromProps<never, any>' is not assignable to type 'GetDerivedStateFromProps<{}, any>'.
                  Types of parameters 'nextProps' and 'nextProps' are incompatible.
                    Type 'Readonly<{}>' is not assignable to type 'never'.ts(2345)

Notas

  • Estoy usando Rollup para transpilar el contenido de la carpeta "src" con archivos de componentes e índice en la carpeta "dist", que termina con index.cjs.js (para CommonJS), index.esm.js (para módulos ES) y un montón de archivos .d.ts generados automáticamente.
  • Estoy usando Yarn link para probar la integración de mi biblioteca externa en mi proyecto Next.js localmente.

Cualquier ayuda es muy apreciada. Gracias de antemano.

Actualización 4 de abril de 2020

En la página oficial de GitHub de Next.js me dijeron que el problema podría haber estado relacionado con el hecho de que dos bibliotecas @types/react estaban cohabitando en el mismo proyecto de Next.js.

Esto es lo que intenté (sin éxito) para probar esta hipótesis:

Ejecuté rápidamente un "yarn why @types/react" y vi lo siguiente:

yarn why v1.22.4
[1/4] 🤔  Why do we have the module "@types/react"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "@types/[email "
info Has been hoisted to "@types/react"
info This module exists because it's specified in "devDependencies".
info Disk size without dependencies: "164KB"
info Disk size with unique dependencies: "1.98MB"
info Disk size with transitive dependencies: "1.98MB"
info Number of shared dependencies: 2
=> Found "@types/react-dom#@types/[email "
info This module exists because "@types#react-dom" depends on it.
info Disk size without dependencies: "164KB"
info Disk size with unique dependencies: "1.98MB"
info Disk size with transitive dependencies: "1.98MB"
info Number of shared dependencies: 2
✨  Done in 0.99s.

Luego probé tres cosas:

  1. Desvincular mi biblioteca > yarn cache clean > reinstalar la biblioteca (esta vez desde un tarball tgz recién generado). El problema persistió
  2. Eliminar @types/react con Yarn de la carpeta de Next.js (dejando efectivamente solo @types/react v16.9.31 elevado desde @types/react-dom). El problema persistió
  3. Eliminé por completo node_modules y yarn.lock y reinstalé todos los paquetes (incluida mi biblioteca desde el archivo tarball). El problema persistió.

Todavía estoy viendo el mismo mensaje de error.

Por cierto, ese mismo componente funciona bien con carga dinámica cuando se importa desde la carpeta de componentes del propio proyecto de Next.js, pero el objetivo es usar el kit de interfaz de usuario externo, obviamente.

Respuesta #1

Aquí está la solución que proviene del GitHub de Next.js por @r0skar:

He hecho lo siguiente:

En mi kit de interfaz externa

export type { ModalProps } from './Modal.interface';

En Next.js

import { ModalProps } from 'my-ui-kit';
const Modal = dynamic<ModalProps>(() => import('my-ui-kit').then((mod) => mod.Modal), {
  ssr: false,
});

Esto hizo feliz a TypeScript (y a mí mismo).

Respuesta #2

Usar funciones async también funcionó para mí. Entonces, tu caso se vería así, creo

const Modal = dynamic(
  async () => (await import('my-ui-kit')).Modal,
  { ssr: false }
);