TypeScript: Importing defaults with es6 syntax doesn't work
Syntax: import name from "module-name"; doesnt work in my project with Typescript 1.6. The imported variable is undefined.
Example:
import createLogger from "redux-logger"; //createLogger is undefined
This syntax works
import createLogger = require("redux-logger");
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 3
- Comments: 22 (7 by maintainers)
You need to write it as a namespace import (as opposed to a default import):
Ok, I think I see what is going on.
It appears the “redux-logger” module was transpiled with Babel. When Babel transpiles a module whose only export is an
export defaultit injects amodule.exports = exports["default"];into the generated code, causing the exported object to become the function itself (instead of a module object that has the function as thedefaultproperty). When paired with the_interopRequireDefaultmagic that Babel generates for imports the net effect is that a fake module object with adefaultproperty is created and the function can now be accessed as_reduxLogger2.default.TypeScript doesn’t do any of this magic (see here for more details). In order for TypeScript to consume the module you need to change the redux-logger.d.ts declaration file to actually reflect what is going on:
Once you do that you should be able to import the module with a namespace import:
or with the equivalent:
@aventurella Thanks. The complexities of ES6 module downlevel transpilation and interop is truly the gift that keeps on giving!
@ahejlsberg I’m using commonjs module loader. I compared my compiled code with babel code and here are two versions:
Typescript:
Babel:
and in the runtime redux_logger_1 is a function and redux_logger_1.default is undefined. Babel code works because the condition inside function is true so it returns
objTo sum up what I’ve said earlier: My goal is to import a node_module which exports one default function. In pure es6 javascript I would do that with
import module from "module". In typescript I tried to do it in the same way with the same syntax but my module variable was undefined during runtime. What is more weird for me this syntax was working when I was trying to link one .ts file to another .ts file.I discovered that Babel compiles default export to another syntax that Typescript and Typescript can’t handle babel output. For example I have the following code:
export default function defaultFunction() {}In babel it will beIn typescript
As I said the first output is incompatible with Typescript. The imports that don’t work:
import defaultFunction from "module"- defaultFunction is undefinedimport { defaultFunction } from "module"- It doesn’t compile if the function is declared as default in definitionsimport * as defaultFunction from "module"- callingdefaultFunction()causes compiler errorerror TS2349: Cannot invoke an expression whose type lacks a call signature.import defaultFunction = require("module");- callingdefaultFunction()causes compiler errorerror TS2349: Cannot invoke an expression whose type lacks a call signature.const defaultFunction = require("module");- works without typescript support but you can add casting to get some intellisenseWith the second output I can just do
import defaultFunction from "module"Thanks @aluanhaddad. I just submitted a new pull request to fix it.
@wy193777 the named export is the problem. I believe you want
based on the package’s source code
Then you would import it via either
or
or referencing the global when not using modules, depending on your environment.
The only way I have been able to “address” it is by understanding how the target 3rd party module has been exported. And you adjust things accordingly once you see how it’s been exported by whatever transpiled it. Once you know that, if you are adding typings you just need to be sure you add them to describe the situation you observe in the 3rd party module.
I know this was closed a while ago, I just wanted to pop in an give a HUGE THANK YOU to @ahejlsberg for that explanation and remedy
remove module.exports = exports["default"];.You just made some things click for me with that. I literally wasted probably 4 hours trying to understand why my type definition, using
export defaultwas returning undefined. Then I stumbled uponexport = Thingand was further scratching my head. Why on earth doesimport * as Thing from 'thing'work withexport = Thingin my definition and then when Iexport default ThingI get undefined withimport Thing from 'thing'. Babel… that’s why. hahahahaha oh man I am so glad I understand this now.I would offer that it’s probably worth adding to the documentation here: https://typescript.codeplex.com/wikipage?title=Writing Definition (.d.ts) Files
As a special note for type definitions for Babel generated code.