Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React/Typescript /VScode - an import path cannot end with a '.tsx' extension

I have a series of react projects which I have converted to typescript. Some of these use webpack, and some of them just use babel as they're libraries which are consumed by the other (webpack) projects/actual applications.

I've converted everything to typescript without problems, except in one non-webpack project, where I receive the error 'an import path cannot end with a .tsx extension', for example on

import LoadingLogo from '../ui/LoadingLogo.tsx';

I can get round this by omitting the extension, or using // @ts-ignore, but neither of these are optimal solutions, since the project will be a mix of jsx and tsx while it is being refactored and I'd like to be able to see at a glance which file type is being used in the import.

The steps I've taken to convert the project to typescript are

  1. Install typescript
  2. Install @babel/preset-typescript
  3. add
presets: [ @babel/preset-typescript ]

to my babel.config.js

To make matters even more confusing, in one of the other (non-webpack) apps, I've got the same babel setup running and I'm not seeing this issue. Is there something obvious I'm missing? For reference, my babel.config in the project with the issue looks like this

module.exports = function(api) {
  api.cache(true);

  return {
    ignore: ['node_modules/**/*'],
    presets: [
      ['@babel/preset-typescript'],
      [
        '@babel/preset-env',
        {
          loose: true,
          targets: {
            node: 'current'
          }
        }
      ],
      '@babel/preset-react'
    ],
    env: {
      translations: {
        plugins: [
          'syntax-async-functions',
          '@babel/plugin-syntax-dynamic-import',
          'dynamic-import-node',
          [
            'react-intl',
            {
              messagesDir: './messages',
              enforceDescriptions: false
            }
          ]
        ]
      },
      production: {
        plugins: [
          'jsx-strip-ext',
          [
            'babel-plugin-styled-components',
            {
              ssr: true
            }
          ],
          'syntax-async-functions',
          '@babel/plugin-syntax-dynamic-import',
          'dynamic-import-node'
        ]
      },
      development: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              ssr: true
            }
          ],
          'syntax-async-functions',
          '@babel/plugin-syntax-dynamic-import',
          'dynamic-import-node'
        ]
      }
    },
    plugins: [
      '@babel/plugin-transform-runtime',
      '@babel/plugin-syntax-dynamic-import',
      '@babel/plugin-syntax-import-meta',
      '@babel/plugin-proposal-class-properties',
      '@babel/plugin-proposal-json-strings',
      '@babel/plugin-transform-classes'
    ]
  };
};

and my babel config in the non-webpack project without the issue looks like this

module.exports = function(api) {
  api.cache(true);

  return {
    presets: ['@babel/preset-typescript'],
    ignore: ['node_modules/**/*'],
    extends: 'myProject/babel.config.js',
    env: {
      production: {
        plugins: [
          [
            'module-resolver',
            {
              alias: {
                '^myProject/src/(.+)': 'myProject/lib/\\1'
              },
              extensions: ['.js', '.jsx'],
              stripExtensions: ['.js', '.jsx']
            }
          ],
          [
            'babel-plugin-styled-components',
            {
              ssr: true
            }
          ],
          'syntax-async-functions',
          '@babel/plugin-syntax-dynamic-import',
          'dynamic-import-node'
        ]
      },
      development: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              ssr: true
            }
          ],
          'syntax-async-functions',
          '@babel/plugin-syntax-dynamic-import',
          'dynamic-import-node'
        ]
      }
    }
  };
};

tsconfig.json for both projects looks like this

{
  "compilerOptions": {
    "module": "esnext",
    "outDir": "dist/",
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "target": "ESNext",
    "allowJs": true,
    "checkJs": false,
    "jsx": "react",
    "pretty": true,
    "skipLibCheck": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "lib": ["dom", "dom.iterable", "ESNext"],
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

My first instinct was to look at the module resolver plugin, but that didn't seem to make any difference. Is there something obvious I'm missing?

like image 560
Muskett Avatar asked Jan 15 '20 17:01

Muskett


People also ask

What is difference between JSX and TSX?

. tsx is similar to jsx except it's TypeScript with the JSX language extension.

What is the difference between TSX and TS?

tsx extension is used when we want to embed JSX elements inside the files while . ts is used for plain Typescript files and do not support adding JSX Elements.

What is TSX file type?

A TSX file is a TypeScript (. TS) file written using JSX syntax. It contains code that is most likely part of a single-page or mobile application. TSX files can be opened in any text editor, but are meant to be opened in source code editors.


1 Answers

I added this to my webpack.config.js and it helped

module.exports = {
  //...
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
  },
};

You might want to add '...' to the end of the array so that it can resolve other extensions. More info about webpack's resolve extension here: https://webpack.js.org/configuration/resolve/#resolveextensions

like image 164
devfromfinland Avatar answered Sep 18 '22 06:09

devfromfinland