assemblyscript icon indicating copy to clipboard operation
assemblyscript copied to clipboard

portability: allow `.js` in import specifiers

Open trusktr opened this issue 2 years ago • 4 comments

It is awkward, but TypeScript officially supports using .js in import specifiers, like so:

import {foo} from './path/to/some/file.js'
console.log(foo)

where ./path/to/some/file.js does not actually exist, but the file ./path/to/some/file.ts actually exists, and TypeScript will correctly (officially) use file.ts.

In fact, to show how official it is, TypeScript more recently even added the feature that when you auto-import something, if you are already use .js extensions in all you import specifiers, the new automatically-added import statement will also have the .js extension for consistency.

But why?

When compiling TypeScript code to JavaScript, we want it to work out of the box in native ES Module systems (like in browsers).

TypeScript team has said they do not (currently at least) wish to modify import specifiers (f.e. converting .ts to .js), but that they officially support .js.

Thus, using the .js extensions makes importing in native ES Module systems easier, because browsers do not yet support things like import 'some/file': the browser will try to load the equivalent of 'current-file-folder/some/file' instead of 'current-file-folder/some/file.js' and it will fail, unless

  • the server is specifically configured to automatically find the matching file with the added extension, but this isn't default behavior in the average static non-js-specific file server.
  • one uses additional build tooling to insert the .js extensions after TypeScript compilation.

This feature would be compatible with TypeScript, and would allow us to compile to WebAssembly or to plain JavaScript with native ES Modules more easily without the extra workarounds.

Some people will despise the feature, but they don't have to use it. And honestly as an engineer that needs to get things done, it's a perfectly fine solution.

trusktr avatar Sep 11 '21 17:09 trusktr

It seems TS support import .js files only with --allowJs option. And this is quite obvious, since TS is trying to smooth the migration from JavaScript to TypeScript and such features are quite appropriate in TS.

MaxGraey avatar Sep 14 '21 07:09 MaxGraey

TS supports .js extensions in TS files like this:

// This file is "foo.ts"

export const foo = 123
// This sibling file imports foo.ts like this:

import {foo} from './foo.js' // totally valid

console.log(foo)

trusktr avatar Nov 17 '21 18:11 trusktr

Node.js requires .js extensions on import specifiers in modern ESM mode, but AssemblyScript can not handle the specifiers.

The --experimental-specifier-resolution=node option for Node.js solves the issue in an experimental way that may or may not be supported later, but works for now!

trusktr avatar Jun 11 '22 19:06 trusktr

It seems TS support import .js files only with --allowJs option. And this is quite obvious, since TS is trying to smooth the migration from JavaScript to TypeScript and such features are quite appropriate in TS.

No, TS supports this for regular TypeScript, with allowJs and checkJs both turned off. It is the standard way to output native ESM code from TypeScript code.

trusktr avatar Jun 11 '22 20:06 trusktr