Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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

  • Install typescript
  • Install @babel/preset-typescript
  • 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?

    FYI I’ve created a ticket similar to this one, but specific to the hurtle I am facing: stackoverflow.com/questions/62437380/… – Matt Rabe Jun 17, 2020 at 20:25

    I renamed my file to navMenus.ts from navMenus.tsx AND changed the way I imported it from:

    import { navMenus } from "../../views/navMenus.tsx";
    
    import { navMenus } from "../../views/navMenus";
    

    this solved the issue

    I'm sorry to say that I doubt you are going to be able to resolve this in the way you desire. TypeScript (specifically TSC) disallows explicit extensions for ts/tsx files... It has to do with implicit file extensions in imports, and how ts/tsx files are compiled down to js/jsx files. The world may not be happy about it, but it seems to be the way that it is.

    You could use // @ts-ignore, but then I think you would lose intellisense

    Update: it has come to my attention from comments below that some TypeScript tools do allow extensions. Evidently Deno requires them, though I have not worked with Deno. The TSC compiler disallows them.

    Some TypeScript tools allow explicit extensions, and others do not. It's not accurate to say that TypeScript prohibits them. In Deno, they're mandatory. In many other runtimes, they're optional. In VS Code's linter, they aren't allowed at all. – Andrew Koster Oct 20, 2020 at 22:27 Good to know. I will update my answer based on that. It should be noted that it was not VSCode that I was referring to as disallowing extensions - it was TSC. – Matt Rabe Oct 21, 2020 at 17:54 By now (I'm using TS 5) one can use ".js" extensions in .ts files. YES you heard that right. TypeScript will know you mean the corresponding .ts file. Extensions are a must-have when you switch to ES modules (and with "type": "module" - or no such property for CommonJS as default - in package.json the extension can always remain ".js"). – Mörre Aug 2, 2023 at 5:39

    To solve your problem, you need:

  • Make sure that you have a tsconfig.json file in the project.json with code
  • "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" "include": ["src"]
  • Check or create a react-app-env.in.ts file with the code
  • /// <reference types="react-scripts" />

    It is this react-app-env.d.ts file that explains TypeScript how to work with ts, tsx, and so on file extensions

  • Remove tsx file extensions in imports. Also remove all extensions that TypeScript will swear at
  • For example before:

    import { Header } from "./Header.tsx";

    This should be the case after removing extensions:

    import { Header } from "./Header";

  • If you had a project running at the time of these changes, stop it and start it again. Since these changes are applied only when the project is started at the compilation stage
  • I'm not sure you've understood what I was asking - the problem I was trying to solve was the opposite of what you have suggested, to have imports WITH the .tsx extension. – Muskett Jun 27, 2022 at 15:17 It's worth noting that with this config, you would have to import ./file.jsx, not ./file.tsx – AirOne Sep 8, 2023 at 7:58

    you need to find @typescript-ESLint in node_modules, open the folder and open the next folder named "@typescript-ESLint", inside this folder modify the file called "package.json".(You should find all of these files/folders for typescript and do this.) Inside the file you should add this:

    "compilerOptions": {
          "allowImportingTsExtensions": "iKnowWhatImDoing"
        "resolve": {
            "extensions": [".js", ".json", ".ts", ".tsx"],
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.