Definitelytyped: React ES6 import issue

Created on 29 Jul 2015  ·  27Comments  ·  Source: DefinitelyTyped/DefinitelyTyped

I try to do this:
import React, {Component} from 'react';

But I don't know how to define the react.d.ts to support this valid ES6 behavior.

The compiler produces this error:
error TS1192: Module '"react"' has no default export.

Most helpful comment

You can use the allowSyntheticDefaultImports compiler option that will allow this kind of import:

import React, {Component} from 'react';

All 27 comments

export default react = React; might just work

I think what you want is import * as React, {Component} from 'react'; (but I could be wrong, still learning some of this as well :smiley:)

So I've spent quite a bit of time with ES6 recently and I believe that currently import React from 'react'; is technically _not_ valid behavior because React does not use ES6 classes modules and therefore cannot specify a default export.

This syntax does work when using Babel but that's because Babel has basically said that "if using an ES6 import to get a CommonJS module, the default export is the same as modules.export. However, this is entirely a Babel thing and not a spec thing. From the perspective of the spec I would say that import * as React from 'react'; is actually a lot closer in spirit (and it does work with TypeScript out-of-the-box).

However, this is entirely a Babel thing and not a spec thing

Agreed. But babel has a _lot_ of traction and people believe that to be the correct way that ES6 modules _should_ behave.

@vvakame has done some work to make the interop with babel type imports smoother : https://github.com/Microsoft/TypeScript/pull/3586

Yea, except that PR is mainly about exporting out of TypeScript, whereas this issue is more about importing into TypeScript. In other words, that PR doesn't help with this issue (but it is definitely good for building libraries with TypeScript!).

I suspect this issue will go away soonish as Babel was acqui-hired by Facebook and I wouldn't be surprised at all if React was rewritten as ES6 modules.

Or, if you _really_ want to use that syntax, you can change the declaration file to export default React but you must target ES6 and then use Babel to transpile to CommonJS, otherwise it's not going to work right at runtime (TypeScript will always transpile to moduleName.default when using ES6 imports).

Thanks for clarifying. In short we have ts export -> babel import working. Now we need module.exports aliased to default -> ts import working.

I'm a bit late to the party, but from what I know, this is a wontfix from the TypeScript team.

tl;dr: you can't translate an export default into an module.exports =. Use the import ... = require(...) legacy syntax instead :(

Since the ES-6 default export is basically just a regular export with the name 'default' , the equivalent in CJS would be an exports.default =. and the import would look like this in CJS var something = require('something').default. The module.exports = syntax is not sufficient because it makes the module equal the exported symbol itself, making circular dependencies impossible to resolve. This goes against the design of the ES6 modules. IMHO the Babel team went a bit overboard with this :(

@dreampulse I'm doing using this syndax:

import {default as React,Component} from 'react';

@kataras that doesn't work for me unfortunately:

Error:(2, 9) TS2305: Module '"react"' has no exported member 'default'.

Code

import {default as React, Component, PropTypes} from 'react';

tsconfig.json

{
  "compileOnSave": true,
  "compilerOptions": {
    "target": "es6",
    "sourceMap": true,
    "jsx": "react"
  }
}

What is working, is having two imports. Like:

import * as React from "react";
import { Component } from "react";

You can use the allowSyntheticDefaultImports compiler option that will allow this kind of import:

import React, {Component} from 'react';

thanks @jbrantly. Spot on!!

@ligaz thanks!

Just for reference, I had to add "module": "es2015", to the tsconfig.json before the fix mentioned by @ligaz worked for me.

I am using import React, {Component, PropTypes} from 'react'; and getting error Cannot resolve symbol PropTypes. Any pointer on how to resolve this issue?

@kkarmalkar If you're using React >=15.5.0, you'll want to migrate from React.PropTypes to the new prop-types package and definitions.

Awesome, thank you @corydeppen

Even though I have allowSyntheticDefaultImports I can't get

import React, {Component} from 'react';

to work, but using

import React from 'react';
import {Component} from 'react';

works fine. I have my module set to es5. When compiling code for the browser is it suggested to use es6? I added es2015 to my libs property in tsconfig.json.

It is related, yes. Curious though that according to this thread it's working for you.

Just add a tsconfig option esModuleInterop: true and then you can use default imports i.e. import React from 'react'

If you're using webpack, then you can also ditch babel with this setup.

This works now. I think it was related to specific versions of webpack and typescript I had been using at the time. Babel setups are unfortunately still required for non-javascript uses of babel.

"allowSyntheticDefaultImports": true

"module": "es2015
“allowSyntheticDefaultImports”:true

Working ....

"module": "es2015
“allowSyntheticDefaultImports”:true

Working ....

Is this a troll? :) Directional quotes on last line, and it's not a colon before true. Should be as following:

  "module": "es2015",
  "allowSyntheticDefaultImports": true

import { default as ProjectInfoProfile } from './ProjectInfoProfile';
or
import ProjectInfoProfile from './ProjectInfoProfile';

in this case, it might work.

"module": "commonjs",
"target": "es6",
"esModuleInterop": true,
"jsx": "react",
"allowSyntheticDefaultImports": true

Was this page helpful?
0 / 5 - 0 ratings