Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

539
Views
Agregar la extensión .js en declaraciones de importación relativas durante la compilación de Typescript (módulos ES6)

Este parece ser un problema trivial, pero no es muy obvio qué ajustes/configuraciones se deben usar para resolver este problema.

Aquí está la estructura del directorio del programa Hello World y el código fuente:

Estructura de directorios:

 | -- HelloWorldProgram | -- HelloWorld.ts | -- index.ts | -- package.json | -- tsconfig.json

índice.ts:

 import {HelloWorld} from "./HelloWorld"; let world = new HelloWorld();

HolaMundo.ts:

 export class HelloWorld { constructor(){ console.log("Hello World!"); } }

paquete.json:

 { "type": "module", "scripts": { "start": "tsc && node index.js" } }

Ahora, la ejecución del comando tsc && node index.js da como resultado el siguiente error:

 internal/modules/run_main.js:54 internalBinding('errors').triggerUncaughtException( ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'HelloWorld' imported from HelloWorld\index.js Did you mean to import ../HelloWorld.js? at finalizeResolution (internal/modules/esm/resolve.js:284:11) at moduleResolve (internal/modules/esm/resolve.js:662:10) at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:752:11) at Loader.resolve (internal/modules/esm/loader.js:97:40) at Loader.getModuleJob (internal/modules/esm/loader.js:242:28) at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:50:40) at link (internal/modules/esm/module_job.js:49:36) { code: 'ERR_MODULE_NOT_FOUND' }

Es obvio que el problema parece haberse originado por el hecho de que en el archivo index.ts no hay extensión .js en la declaración de importación ( import {HelloWorld} from "./HelloWorld"; ). Typescript no arrojó ningún error durante la compilación. Sin embargo, durante el tiempo de ejecución, Node (v14.4.0) quiere la extensión .js .

Espero que el contexto sea claro.

Ahora, cómo cambiar la configuración de salida del compilador (tsconfig.json o cualquier indicador) para que la ruta relativa local importe como import {HelloWorld} from ./Helloworld; será reemplazado por import {HelloWorld} from ./Helloworld.js; durante la compilación de Typescript a Javascript en el archivo index.js ?

Nota: It is possible to directly use the .js extension while importing inside typescript file. However, it doesn't help much while working with hundreds of old typescript modules, because then we have to go back and manually add .js extension. Rather than that for us better solution is to batch rename and remove all the .js extension from all the generated .js filenames at last.

over 4 years ago · Santiago Trujillo
6 answers
Answer question

0

Por lo general, solo uso la extensión .js en declaraciones de importación en archivos mecanografiados y funciona.

No usar una extensión de archivo en las rutas de importación es algo exclusivo de nodejs. Como no está usando commonjs sino un módulo, no está usando nodejs. Por lo tanto, debe usar la extensión .is en las rutas de importación.

over 4 years ago · Santiago Trujillo Report

0

TypeScript no puede saber qué URI va a usar para servir sus archivos, por lo tanto, simplemente debe confiar en que la ruta del módulo que le proporcionó es correcta. En este caso, le dio una ruta a un URI que no existe, pero TypeScript no puede saberlo, por lo que no hay nada que pueda hacer al respecto.

Si está sirviendo el módulo con un URI que termina en .js , entonces la ruta de su módulo debe terminar en .js . Si la ruta de su módulo no termina en .js , entonces debe servirlo en un URI que no termine en .js .

Tenga en cuenta que el W3C desaconseja encarecidamente el uso de extensiones de archivo en los URI , ya que dificulta la evolución de su sistema y aboga por confiar en la negociación de contenido.

Reescribir las rutas rompería un par de principios de diseño fundamentales de TypeScript. Un principio de diseño es que TypeScript es un superconjunto adecuado de ECMAScript y cada programa y módulo de ECMAScript válido es un programa y módulo de TypeScript semánticamente equivalente. Reescribir las rutas rompería ese principio, porque una parte de ECMAScript se comportaría de manera diferente dependiendo de si se ejecuta como ECMAScript o TypeScript. Imagina, tienes el siguiente código:

./Hola

 export default "ECMAScript";

./hola.js

 export default "TypeScript";

./principal

 import Hello from "./hello"; console.log(Hello);

Si TypeScript hizo lo que sugiere, esto imprimiría dos cosas diferentes dependiendo de si lo ejecuta como ECMAScript o como TypeScript, pero los principios de diseño de TypeScript dicen que TypeScript nunca cambia el significado de ECMAScript . Cuando ejecuto una pieza de ECMAScript como TypeScript, debería comportarse exactamente como lo hace cuando la ejecuto como ECMAScript.

over 4 years ago · Santiago Trujillo Report

0

Para los compañeros desarrolladores que buscan una solución a este problema, las posibles soluciones que hemos encontrado son las siguientes:

  1. Para los archivos nuevos, es posible simplemente agregar la extensión ".js" en la declaración de importación en el archivo Typescript mientras se edita. Ejemplo: import {HelloWorld} from "./HelloWorld.js";

  2. Si trabaja con proyectos antiguos, en lugar de revisar todos y cada uno de los archivos y actualizar las declaraciones de importación, nos resultó más fácil cambiar el nombre por lotes y eliminar la extensión ".js" del Javascript generado a través de un simple script automatizado. Sin embargo, tenga en cuenta que esto podría requerir un cambio menor en el código del lado del servidor para servir estos archivos ".js" sin extensión con el tipo MIME adecuado para los clientes. Si desea evitar esto, puede usar expresiones regulares para buscar por lotes y reemplazar las instrucciones de importación de forma recursiva para agregar la extensión .js .

Nota al margen:

Con respecto al fracaso del equipo de TS para resolver este problema, parece que hay una tendencia a tratar de sacar este problema de contexto de lo que realmente es y adjuntarlo a algunos principios de diseño para defenderlo.

Sin embargo, de hecho, esto no es más que un problema con la forma en que el compilador trata asimétricamente con la extensión . El compilador de TypeScript permite importar declaraciones sin una extensión. Luego agrega la extensión ".js" al nombre de archivo de salida correspondiente mientras se traduce el archivo, pero para las declaraciones de importación correspondientes donde se hace referencia a este archivo, ignora el hecho de que agregó la extensión ".js" durante la traducción. ¿Cómo se puede defender esta asimetría con los principios de reescritura de URI fuera de contexto?

Hay una correspondencia fija uno a uno entre el archivo Typescript y el archivo de salida Javascript generado durante la compilación. Si la importación a la que se hace referencia no existe, el compilador arrojaría un error. ¡Los archivos ni siquiera se compilarían! Por lo tanto, los ejemplos fuera de contexto o no compilables que mencionan la posibilidad de otros URI en conflicto invalidan tales afirmaciones.

Si el compilador simplemente generara archivos de salida sin extensión, también resolvería el problema . Pero, ¿eso también violaría de alguna manera el principio de diseño con respecto a las reescrituras de URI? ¡Ciertamente, en ese caso podrían existir otros principios de diseño para defender la posición! Pero, ¿no ayudaría tal terquedad a validar aún más la inflexibilidad o la ignorancia del equipo de TS sobre este tema?

over 4 years ago · Santiago Trujillo Report

0

también puede agregar banderas CLI de nodejs para habilitar node module resolution :

  • para importar json --experimental-json-modules
  • para importar sin extensiones --experimental-specifier-resolution=node

Sé que --experimental-specifier-resolution=node tiene un error (o no), entonces no puede ejecutar scripts bin sin extensiones (por ejemplo, en package.json bin "tsc" no funciona, pero "tsc":"tsc. js" funcionará). Muchos paquetes tienen secuencias de comandos bin sin ninguna extensión, por lo que hay algunos problemas al agregar la variable de NODE_OPTIONS="--experimental-specifier-resolution=node"

over 4 years ago · Santiago Trujillo Report

0

Puedes usar la misma solución que yo.

Archivo: tsconfig.json

 "compilerOptions": { "module": "commonjs", ==> not required extension when import "target": "ES6", },

Debido a que usa commonjs, debe eliminar "type": "module" en package.json

Listo :D

over 4 years ago · Santiago Trujillo Report

0

Como muchos han señalado. La razón por la que Typescript no agrega y nunca agregará la extensión de archivo a las declaraciones de importación es su premisa de que la transpilación de código javascript puro debe generar el mismo código javascript.

Creo que lo mejor que podrían hacer sería tener un indicador para hacer que TypeScript aplique extensiones de archivo en declaraciones de importación. Entonces, los linters como eslint podrían ofrecer un reparador automático basado en esa regla.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!