'node_modules/@types/react/index"' has no default export

Trying to convert a React app over into Typescript and running into strange errors.

node_modules/@types/react/index"' has no default export.

node_modules/@types/react-dom/index"' has no default export.

I have my tsconfig and webpack setup for typescript. After changing this one component's extension from .js to .tsx I'm getting errors for React?

enter image description here

Thoughts?

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./moonholdings/",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es5",
    "jsx": "react"
  },
  "include": [
    "./app/**/*"
  ]
}

webpack

/* eslint-disable no-console */
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import path from 'path';
import chalk from 'chalk';

const moonholdings = path.resolve(__dirname, 'moonholdings');
const app = path.resolve(__dirname, 'app');
const nodeModules = path.resolve(__dirname, 'node_modules');

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: path.join(__dirname, '/app/index.html'),
  inject: 'body'
});

const ExtractTextPluginConfig = new ExtractTextPlugin({
  filename: 'moonholdings.css',
  disable: false,
  allChunks: true
});

const CopyWebpackPluginConfigOptions = [{
  from: 'app/static',
  to: 'static/'
}];

const CopyWebpackPluginConfig = new CopyWebpackPlugin(CopyWebpackPluginConfigOptions);

const PATHS = {
  app,
  build: moonholdings
};

const LAUNCH_COMMAND = process.env.npm_lifecycle_event;

const isProduction = LAUNCH_COMMAND === 'production';
process.env.BABEL_ENV = LAUNCH_COMMAND;

const productionPlugin = new webpack.DefinePlugin({
  'process.env': {
    NODE_ENV: JSON.stringify('production')
  }
});

const base = {
  // entry: ['babel-polyfill', PATHS.app],
  entry: './app/index.tsx',
  output: {
    path: PATHS.build,
    publicPath: '/',
    filename: 'index_bundle.js'
  },
  resolve: {
    modules: [app, nodeModules],
    extensions: ['.ts', '.tsx', '.js', '.json']
  },
  module: {
    rules: [
      // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
      { test: /\.tsx?$/, loader: 'awesome-typescript-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.s?css/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)/,
        loader: 'file-loader?name=[path][name].[ext]'
      },
      // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
      { enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' }
    ]
  }
};

const developmentConfig = {
  devtool: 'cheap-module-inline-source-map',
  devServer: {
    contentBase: moonholdings
  },
  plugins: [
    CopyWebpackPluginConfig,
    ExtractTextPluginConfig,
    HtmlWebpackPluginConfig
  ]
};

const productionConfig = {
  devtool: 'cheap-module-source-map',
  plugins: [
    CopyWebpackPluginConfig,
    ExtractTextPluginConfig,
    HtmlWebpackPluginConfig,
    productionPlugin
  ]
};

console.log(`${chalk.magenta('฿')} ${chalk.green('yarn run:')} ${chalk.red(LAUNCH_COMMAND)}`);

export default Object.assign(
  {}, base,
  isProduction === true ? productionConfig : developmentConfig
);


Solution 1:[1]

You have to use import * as React from "react"; instead of import React from 'react'.

That happens because babel (the one that you were using before) assumes modules.export as default export while typescript (the one that you are using now) does not.

Solution 2:[2]

You can use this syntax by simply adding "allowSyntheticDefaultImports": true and "esModuleInterop":true to your tsconfig.json

{
  ...
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
  },
  ...
}

Solution 3:[3]

I was having a similar issue while using Next.js and found out it's possible to simply omit the import declaration in this case. A component like the following would have the first line removed.

import React from "react"; // Delete this line

function MyComponent(): JSX.Element {
  return (
    <div>MyComponent</div>
  );
}

export default MyComponent;

It's still possible to import components, hooks, etc. from React if needed, e.g.:

import { useState } from "react";

Notice I already had the options describe in GoalsAndGambles' answer added to my tsconfig.json file.

Solution 4:[4]

Add a react-shim.js file at project root with following content:

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 QoP
Solution 2
Solution 3 Gustavo Straube
Solution 4 William Nemencha