You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
export const x = expr as Generic<A, B> produces a phantom export named after B, colliding when 2+ such casts share a last type arg #296
import-in-the-middle's ESM export scanner (lib/get-esm-exports.mjs → es-module-lexer) misparses a specific TypeScript cast shape: export const x = expr as GenericType<Arg1, Arg2>;. When the cast target has 2+ comma-separated type arguments, the scanner emits a phantom second export named after the literal text of the last type argument — not tied to any real binding.
Not specific to the word unknown — swapping it for number produces a phantom number export instead. But unknown is exactly what codegen tools emit as the trailing type arg for typed documents with no variables (e.g. graphql-code-generator's typed-document-node plugin: export const MyQueryDocument = {...} as unknown as DocumentNode<MyQuery, unknown>;). Any generated file with 2+ such exports gets two phantom "unknown" exports, which collide in the generated wrapper module — invalid ESM, crashes the module linker before user code runs:
file:///.../types.ts?iitm=true:16
export { $0 as "foo", $1 as "unknown", $2 as "bar", $3 as "unknown" }
^^^^^^^^^^^^^^^
SyntaxError: Duplicate export of 'unknown'
Environment
import-in-the-middle: reproduces on 3.5.0 and 3.5.1 (latest)
Node.js: v26.3.0 locally; also seen on v24.21.0 in production
Triggered via Node's native TypeScript execution (running .ts files directly, no separate transpile step) combined with --experimental-loader=import-in-the-middle/hook.mjs
Boundary conditions checked
Single-arg generic cast (1 as Array<unknown>) — no phantom export.
Type annotation instead of cast (const foo: Generic<A, B> = ...) — no phantom export.
Only a cast expression as Generic<Arg1, Arg2> with 2+ type args triggers it; phantom export name = last type argument's text.
I can take this. I’ll reproduce it against current main through the native TypeScript loader path, add a regression around multiple generic-cast exports, and keep the fix scoped to TypeScript export discovery.
Please update your dependencies and verify the behavior with the latest es-module-lexer version being just released. It would be pulled in automatically
Activity
tayfuryldz commentedon Sep 18, 2026
I can take this. I’ll reproduce it against current main through the native TypeScript loader path, add a regression around multiple generic-cast exports, and keep the fix scoped to TypeScript export discovery.
BridgeAR commentedon Oct 5, 2026
Please update your dependencies and verify the behavior with the latest es-module-lexer version being just released. It would be pulled in automatically
BridgeAR commentedon Oct 15, 2026
Closing as resolved with the latest es-module-lexer version