Repository navigation
import * as alias syntax doesn't work with export = function unless merged with namespace #5073
Description
Activity
there is no way in an ES6 module to achieve this. the parallel in an ES6 module world is to
defaultexport.import *will import the namespace component of the export, if it exists, if it does not, it is an error. That you can call the alias as a function in the second case, is the bug i would say.Reacted by soerenBoisen and Andrew Ross- addedBy DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead
on Oct 2, 2015 - added a commit that references this issue
on Jan 31, 2016 - added a commit that references this issue
on Feb 3, 2016 - added a commit that references this issue
on Apr 14, 2016 - added a commit that references this issue
on Apr 14, 2016 - added a commit that references this issue
on May 21, 2016 - added a commit that references this issue
on May 24, 2016 - added 2 commits that reference this issue
on Jul 26, 2016 - added 2 commits that reference this issue
on Aug 9, 2016 8 remaining items
blakeembrey commented
on Aug 27, 2016 ContributorMore actionswhat does it mean for users who would want to run this in a non-commonjs engine? e.g. ES6 enabled web browser? require does not make sense here.
Mohamed Hegazy (@mhegazy) To follow up on that, the
namespace {}hack proposed and used in every linked issue here enables the behaviour you describe. It seems there's enough people committing the hack (and having it merged) that it would warrant looking at whether you should enableimport x = require('x'). If not, perhaps those PRs should start being rejected with proper guidance on how to use the import syntax in these cases (E.g. by recommending people use CommonJS modules instead of ES6 or just informing people ofimport x = require('x')- I've found enough people just didn't know theimport x =style existed it or have tried to enforce a style without understanding the implications and then use this hack to make things work instead).Reacted by Alex, Robert K. Bell, Frederick Fogerty, Andrew Ross, normalser, Jiayi Hu and Pkmmte Xeleon- added a commit that references this issue
on Oct 19, 2016 Without the hack, TS code cannot target es6 if it consumes cjs module.
With Babel, JS user is doing
import x from 'x'and it is working fine for them.
For TS, right now we do not have any working solution except the hack.Reacted by soerenBoisenI still can't tell if this was ever intended behavior or not (that using the namespace allows this to pass typecheck), or just a happy accident that now too many people rely on to change.n
It seems an empty namespace gets SymbolType NamespaceModule (1024) and the checker looks for the merged symbol. So basically
function C {} // symbol type 16
namespace C {} // symbol type 1024
(1024 | 16) & SymbolFlags.Module == true (fromresolveESModuleSymbolincompiler/checker.ts)is what I think is happening?
The PR that added module support #2242 explicitly mentions:
A module that uses export = to export a non-module entity in place of the module itself must be imported using the existing import x = require("foo") syntax as is the case today.
But I don't understand what typescript considers a non-module entity. The actual line in checker that flags these errors is:
(!dontResolveAlias && symbol && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)))So I can get away with pretty confusing stuff like:
a.ts const x = () => 1; export = x;b.ts import * as x from './a'; x()Which passes compilation fine as with
./node_modules/.bin/tsc b.ts -t "es6" -m "amd".Is a module entity related to https://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects, which is what the es6 grammar specifies is the type of
import * as foo?- added a commit that references this issue
on Jun 7, 2017 So, is this the hack?
And is it still the best way?declare module 'nedb-core' { class Datastore { constructor(options?: {}) } namespace Datastore { } export = Datastore }
Reacted by the L, Andres Elizondo and Glavin WiechertMihail Malo (@qm3ster) I think so.. I don't like the consistency here..have you found any solution for this???
the L (@LouisWayne) well, the reason a hack might be the best we can do is because we are trying to ES6-import something that could never have been ES6-exported.
I am currently doing what I wrote above and not having any problems.- added a commit that references this issue
on Mar 21, 2018 - added a commit that references this issue
on Mar 21, 2018 With
esModuleInteropavailable, you should not need this hack anymore.
You should be able to do:import x from 'cjs' // instead of import * as x from 'cjs'
Reacted by the L, Sasha Odinok, Tom Clift, Thom Nichols, Anton Rudeshko, Matthew Radcliffe and Florian KörnerReacted by Matthew RadcliffeThanks!
esModuleInteropworks like a sharm!- locked and limited conversation to collaborators
on Jul 25, 2018
Can't be included via
import * as f from "foo";.(
test.ts(1,20): error TS2497: Module '"foo"' resolves to a non-module entity and cannot be imported using this construct.)Whereas
Can be. The distinction seems artificial.