loaders icon indicating copy to clipboard operation
loaders copied to clipboard

--experimental-strip-types should elide imported types

Open davidfiala opened this issue 1 year ago • 5 comments

Node Version: v22.9.0

Command: node --experimental-strip-types example.ts

import { Http2SecureServer } from 'http2'; // causes error

//import type { Http2SecureServer } from 'http2'; // no error

console.log('done');
import { Http2SecureServer } from 'http2'; // causes error
         ^^^^^^^^^^^^^^^^^
SyntaxError: The requested module 'http2' does not provide an export named 'Http2SecureServer'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:171:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:254:5)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:483:26)

When I import a built in type using import type ... everything seems OK. I wonder if -experimental-strip-types needs to rewrite imports in some cases?

davidfiala avatar Oct 09 '24 22:10 davidfiala

Apologies- this was in part my mistake. Http2SecureServer is not exported by node:http2. The user error was that the IDE and bundler let me get away with the import without using the type keyword.

I think this does bring up an interesting question though: bundlers disregard things exported as a type and only used as a type. It's much harder for --experimental-strip-types to know which imports it can disregard until after it's done a full pass of the source code. And even then, I wonder if it's idempotent to skip any import that was never used as anything except a type.

davidfiala avatar Oct 09 '24 23:10 davidfiala

It's much harder for --experimental-strip-types to know which imports it can disregard until after it's done a full pass of the source code. And even then, I wonder if it's idempotent to skip any import that was never used as anything except a type.

According to the spec, importing a specific named imports should not be observable IIUC (i.e. import {whatever} from 'specifier' and import 'specifier' should be equivalent as long as whatever is not used). That being said, it's probably quite tricky to reliably assess whether something is only used as a type, and would come with some speed tradeoff I assume.

The user error was that the IDE and bundler let me get away with the import without using the type keyword.

FWIW, there's verbatimModuleSyntax to avoid this trap – as well as a lint rule.

aduh95 avatar Oct 09 '24 23:10 aduh95

Thank you for the tips!

davidfiala avatar Oct 10 '24 00:10 davidfiala

That being said, it's probably quite tricky to reliably assess whether something is only used as a type, and would come with some speed tradeoff I assume.

It's is impossible to determine that reliably (because the binding could be re-exported). That's why typescript introduced isolatedModules very long ago :)

nicolo-ribaudo avatar Oct 10 '24 08:10 nicolo-ribaudo

Note to self: what I'm looking for is called import elision and is documented very nicely with caveats within typescript 5.0+ verbatimModuleSyntax flag.

Discussed here per the earlier link: https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax

As a result, I'm renaming the issue to --experimental-strip-types should elide imported types

davidfiala avatar Jan 09 '25 16:01 davidfiala