The Three Easiest Ways to Fix the “Missing File Extension ‘tsx'” Error

Many different options exist for fixing the “Missing file extension ‘tsx’ error”. Once it is fixed, you will be able to import from a TypeScript file. Often this error is present in create-react-app default setup when you try to use TypeScript files.

After a lot of testing, I found three simple methods for fixing the “Missing file extension ‘tsx’ error”. This seems like something that should ‘just work’ when the @typescript-eslint plugin is enabled, and it’s frustrating that was difficult to fix.

Here are the three methods summarized (#2 is the best with create-react-app):

  • Add resolve.extensions: [".tsx"] to webpack.config.js – only works if you have access to webpack.config.js
  • Add extends: ["airbnb-typescript"] to .eslintrc.json – only works if you are using eslint-config-airbnb
  • Use eslint-import-resolver-typescript plugin – this option requires more configuration but works when the above two options are not available

These three options are explained in more detail below. I include a fully configured .eslintrc.json file for the second and third options.

Missing file extension for tsx file
Missing file extension for Human.tsx file

How to Allow tsx File Extensions Using webpack.config.js

If you can access webpack.config.js, then you can support .tsx extensions with the following code:

  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  }

(See webpack docs on tsx support here).

The problem is, if you generate your app using create-react-app then webpack.config.js is hidden in node modules.

Three options for overriding the config exist even if you use create-react-app:

  • Create React App Configuration Override (craco) – create your own config file that overrides CRA configs.
  • react-app-rewired – similar to craco in that you can add configs and plugins to the app generated by CRA
  • Call npm run eject in your CRA app – ejects your webpack.config.js so you can tweak it. Probably this is not needed anymore because all other methods in this post are better.

How to Allow tsx File Extensions Using eslint-config-airbnb-typescript (Best with create-react-app)

eslint-config-airbnb-typescript is a plugin that adds TypeScript support to AirBnB’s ESLint configuration. Follow the steps from the documentation, which I have summarized below:

  • Install eslint-config-airbnb-typescript
  • Make sure dev dependencies @typescript-eslint/eslint-plugin and @typescript-eslint/parser are at major version 5
  • Add extends: ["airbnb-typescript"] to .eslintrc.json
  • Add parserOptions.project: ["tsconfig.json"] to .eslintrc.json

Here’s an example .eslintrc.json with this setup:

{
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "plugin:react/recommended",
        "airbnb",
        "airbnb-typescript"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module",
        "project": ["tsconfig.json"]
    },
    "plugins": [
        "react",
        "@typescript-eslint"
    ]
}

Special thanks to this SO answer by Ryan Wheale.

This is the setup that I use.

How to Allow tsx File Extensions with eslint-import-resolver-typescript

eslint-import-resolver-typescript is a plugin that adds TypeScript support to eslint-plugin-import.

I use the @typescript-eslint plugin in my project and eslint-import-resolver-typescript is add .tsx file extension support to that plugin as well.

Use eslint-import-resolver-typescript if you cannot update the webpack config file and you aren’t using AirBnB’s ESLint setup.

See the documentation here.

Install eslint-import-resolver-typescript

Step one is installing the plugin. Here is the npm package link.

Remember to install the plugin as a dev dependency. Here is the suggested npm install script:

npm i -D eslint-import-resolver-typescript

Also install eslint-plugin-import and @typescript-eslint/parser if you have not. These are required for adding .tsx file import support with ESLint and Typescript-ESLint.

Add TypeScript to the Import/Resolver

Step Two is to add the following value at the root of your .eslintrc.json file:

"settings": {
    "import/resolver": {
        "typescript": {
            "alwaysTryTypes": true
        }
    }
}

From the npm page’s configuration section, this config always tries to resolve types under the <root>@types directory.

I am not sure why this is required for .tsx files to be imported, but if this is removed then the error returns.

Configure the .eslintrc.json Import/Extensions Rule

Step Three is to add the plugin rule to your .eslintrc.json rules section.

There are two options:

  • Turn off the import/extensions rule for all extensions
  • Turn off the rule for specific extensions (this is usually the better plan)

Add this single line to your rules section if you want to turn of lint checking for all extensions:

"import/extensions": "off"

Add the below code to turn off specific extension checking:

"rules": {
    "import/extensions": [
        "error",
        "always",
        {
            "pattern": {
                "jsx": "never",
                "tsx": "never"
            }
        }
    ]
}

The “error” value means the compiler will error instead of simply log a warning.

The “always” value means for all unspecified extensions the compiler should still require extensions.

The “pattern” value is where you can specify which extensions are not required.

Here is an example .eslintrc.json. It has a basic configuration plus the import/extensions rule set up to allow for .tsx file extensions.

{
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "plugin:react/recommended",
        "airbnb"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "@typescript-eslint"
    ],
    "rules": {
        //"import/extensions": "off",
        "import/extensions": [
            "error",
            "always",
            {
                "pattern": {
                    "jsx": "never",
                    "tsx": "never"
                }
            }
        ]
    },
    "settings": {
        "import/resolver": {
            "typescript": {
                "alwaysTryTypes": true
            }
        }
    }
}

Resources

Here’s how to set up globals in your .eslintrc.json file.

Here’s how to use the @typescript-eslint/ban-types rule.

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.