He cambiado el código de un proyecto realizado en NodeJS a Typescript. Todo funciona bien, excepto por el hecho de que aparentemente un paquete de una tercera parte (tipo de archivo, https://www.npmjs.com/package/file-type ) no parece aceptar el require que se genera en el compilado. archivos .js . Para cambiar eso, tengo que cambiar la propiedad "módulo" de tsconfig.json a otro valor que no sea "commonjs". Sin embargo, rompe el código y genera muchos problemas.
Mi tsconfig.json:
{ "compilerOptions": { "target": "es6", "module": "commonjs", "allowJs": true, "lib": ["ES6"], "esModuleInterop": true, "moduleResolution": "node", "outDir": "build", "rootDir": "src", "skipLibCheck": true, "strict": true } }El error que obtengo:
const filetype = __importStar(require("file-type")); ^ Error [ERR_REQUIRE_ESM]: require() of ES Module C:\Users\user\Desktop\repos\art-api\node_modules\file-type\index.js from C:\Users\user\Desktop\repos\art-api\build\middlewares\process-image.js not supported. Instead change the require of index.js in C:\Users\user\Desktop\repos\art-api\build\middlewares\process-image.js to a dynamic import() which is available in all CommonJS modules. at Object.<anonymous> (C:\Users\user\Desktop\repos\art-api\build\middlewares\process-image.js:33:31) at Object.<anonymous> (C:\Users\user\Desktop\repos\art-api\build\controllers\artworkControllers.js:19:25) at Object.<anonymous> (C:\Users\user\Desktop\repos\art-api\build\routers\artworkRouter.js:7:30) at Object.<anonymous> (C:\Users\user\Desktop\repos\art-api\build\server.js:9:41) { code: 'ERR_REQUIRE_ESM' }Aparentemente, el problema es que el código generado en JavaScript entra en conflicto con el código del paquete, que usa la sintaxis de exportación de ES6. Si esto es correcto, ¿cómo puedo solucionar este problema? ¿Hay alguna manera de generar código .js con sintaxis de importación solo para este paquete en particular, o alguna solución como esa? Otras partes del código no me dan ningún problema, solo la importación de este paquete (tipo de archivo).
Por si acaso, este es el index.js de 'file-type', donde tiene la importación de la que se queja el compilador:
import * as strtok3 from 'strtok3'; import {fileTypeFromTokenizer} from './core.js'; export async function fileTypeFromFile(path) { const tokenizer = await strtok3.fromFile(path); try { return await fileTypeFromTokenizer(tokenizer); } finally { await tokenizer.close(); } } export * from './core.js';Bueno, después de investigar un poco, pude entender y solucionar el problema.
El punto es que el paquete que estoy usando, tipo de archivo , no tiene compatibilidad con la sintaxis CommonJS require() . Por lo tanto, al establecer
"module": "commonJS" En mi archivo tsconfig.json , el archivo javascript compilado equivalente usaría require() ; más específicamente, de esta manera:
const file_type_1 = __importDefault(require("file-type"));O algunas variaciones como:
const filetype = __importStar(require("file-type")); Estaba en conflicto con el archivo index.js de file-type , que usa una exportación predeterminada , como puede ver en el código publicado junto con mi pregunta.
1 - Cambie "module": "commonJS" a "module": "ES6" en tsconfig.json
Probablemente dará como resultado errores como "No se puede usar la declaración de importación fuera de un módulo" . Sucede porque acabamos de cambiar la sintaxis de los archivos .js compilados, que ahora tienen la sintaxis de import/export en lugar de require() . Para que NodeJS maneje esto, debemos seguir el segundo paso:
2 - Agregue "type":"module" en package.json
3 - Cambio extensión de importaciones relativas
El segundo paso resolverá el primer problema, pero luego tendremos que usar la ruta completa al importar archivos, es decir, agregar .js en las importaciones relativas. Asi que,
import getImageRouter from './routers/imageRouter';se convierte
import getImageRouter from './routers/imageRouter.js';Sí, aunque parezca raro, usamos la extensión .js en las importaciones. Typescript será lo suficientemente inteligente como para resolverlo durante el tiempo de compilación.
Estos pasos resolvieron el problema para mí.
Gran explicación de las propiedades de tsconfig.json : https://medium.com/@tommedema/typescript-confusion-tsconfig-json-module-modulesolution-target-lib-explained-65db2c44b491
Módulos ECMAScript en Node.js: https://www.typescriptlang.org/docs/handbook/esm-node.html
Un poco más sobre la importación de archivos con la extensión .js: agregar la extensión .js en declaraciones de importación relativas durante la compilación de TypeScript (módulos ES6)