Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

import * as alias syntax doesn't work with export = function unless merged with namespace #5073

Closed
weswigham opened this issue Oct 2, 2015 · 17 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@weswigham
Copy link
Member

declare module "foo" {
  function foo(): void;
  export = foo;
}

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

declare module "foo" {
  function foo(): void;
  namespace foo {}
  export = foo;
}

Can be. The distinction seems artificial.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 2, 2015

there is no way in an ES6 module to achieve this. the parallel in an ES6 module world is to default export. 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.

@mhegazy mhegazy added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Oct 2, 2015
@mhegazy mhegazy closed this as completed Oct 2, 2015
liushigit added a commit to liushigit/DefinitelyTyped that referenced this issue Apr 14, 2016
Without this, there will be `Module '"koa-bodyparser"' resolves to a non-module entity and cannot be imported using this construct. (2497)` error
This solution is found (here)[microsoft/TypeScript#5073].
koa-json's `.d.ts` file has such namespace.
horiuchi pushed a commit to DefinitelyTyped/DefinitelyTyped that referenced this issue Apr 14, 2016
Without this, there will be `Module '"koa-bodyparser"' resolves to a non-module entity and cannot be imported using this construct. (2497)` error
This solution is found (here)[microsoft/TypeScript#5073].
koa-json's `.d.ts` file has such namespace.
vvakame pushed a commit to DefinitelyTyped/DefinitelyTyped that referenced this issue Apr 14, 2016
Without this, there will be `Module '"koa-bodyparser"' resolves to a non-module entity and cannot be imported using this construct. (2497)` error
This solution is found (here)[microsoft/TypeScript#5073].
koa-json's `.d.ts` file has such namespace.
vvakame pushed a commit to DefinitelyTyped/DefinitelyTyped that referenced this issue Apr 17, 2016
* added svgRendering property to Html2CanvasOptions interface

* added an empty namespace in koa-bodyparser.d.ts (#8979)

Without this, there will be `Module '"koa-bodyparser"' resolves to a non-module entity and cannot be imported using this construct. (2497)` error
This solution is found (here)[microsoft/TypeScript#5073].
koa-json's `.d.ts` file has such namespace.

* Missing locale functions and types
tkrotoff added a commit to tkrotoff/DefinitelyTyped that referenced this issue May 21, 2016
vvakame pushed a commit to DefinitelyTyped/DefinitelyTyped that referenced this issue May 24, 2016
* Boostrap -> Bootstrap

* Allow ES6 import syntax for wolfy87-eventemitter.d.ts

See microsoft/TypeScript#5073
garthk added a commit to garthk/DefinitelyTyped that referenced this issue Jul 26, 2016
Per microsoft/TypeScript#5073, closed as `By Design` by @mhegazy,
we need to merge a namespace with the export when using `export =`,
otherwise `import *` must fail.
garthk added a commit to garthk/DefinitelyTyped that referenced this issue Jul 26, 2016
Per microsoft/TypeScript#5073, closed as `By Design` by @mhegazy, we need to
export a namespace for `import *` to work, else `TS2497`. That clashes with
the `export = ClassName` pattern unless you also merge in a namespace, e.g.
with `namespace ClassName {}`.
@unional
Copy link
Contributor

unional commented Apr 4, 2017

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.

@byrgvt
Copy link

byrgvt commented May 3, 2017

I 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 (from resolveESModuleSymbol in compiler/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?

spectralradius added a commit to spectralradius/websocket-json-stream that referenced this issue May 24, 2017
gnain added a commit to gnain/DefinitelyTyped that referenced this issue Jun 7, 2017
@qm3ster
Copy link

qm3ster commented Dec 5, 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
}

@LouisWayne
Copy link

@qm3ster I think so.. I don't like the consistency here..have you found any solution for this???

@qm3ster
Copy link

qm3ster commented Jan 3, 2018

@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.

claytonsilva added a commit to claytonsilva/cep-promise that referenced this issue Mar 8, 2018
in issue BrasilAPI#112, we saw the problem with angular 5.

in my tests, i install angular 5 and rollback the definition without workarround
solved for default function microsoft/TypeScript#5073

and this back work, i think this worked because typescript can have a fix in recent version.
ljani added a commit to ljani/tslint-webpack-plugin that referenced this issue Mar 21, 2018
Apparently import * as alias syntax does not work with export = function:
microsoft/TypeScript#5073
jrparish pushed a commit to jrparish/tslint-webpack-plugin that referenced this issue Mar 21, 2018
* Prefer a namespace over declare module

Apparently import * as alias syntax does not work with export = function:
microsoft/TypeScript#5073

* TslintOptions already includes format
@unional
Copy link
Contributor

unional commented Mar 24, 2018

With esModuleInterop available, you should not need this hack anymore.
You should be able to do:

import x from 'cjs'

// instead of 
import * as x from 'cjs'

@aodinok
Copy link

aodinok commented Apr 2, 2018

Thanks! esModuleInterop works like a sharm!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

8 participants