Skip to main content

ESLint FAQs

Why is a rule from ESLint core not working correctly with TypeScript code?

This happens because TypeScript adds new features that ESLint doesn't know about.

The first step is to check our list of "extension" rules here. An extension rule is a rule which extends the base ESLint rules to support TypeScript syntax. If you find it in there, give it a go to see if it works for you. You can configure it by disabling the base rule, and turning on the extension rule. Here's an example with the semi rule:

{
"rules": {
"semi": "off",
"@typescript-eslint/semi": "error"
}
}

If you don't find an existing extension rule, or the extension rule doesn't work for your case, then you can go ahead and check our issues. The contributing guide outlines the best way to raise an issue.

We release a new version our tooling every week. Please ensure that you check our the latest list of "extension" rules before filing an issue.

I get errors from the no-undef rule about global variables not being defined, even though there are no TypeScript errors

The no-undef lint rule does not use TypeScript to determine the global variables that exist - instead, it relies upon ESLint's configuration.

We strongly recommend that you do not use the no-undef lint rule on TypeScript projects. The checks it provides are already provided by TypeScript without the need for configuration - TypeScript just does this significantly better.

As of our v4.0.0 release, this also applies to types. If you use global types from a 3rd party package (i.e. anything from an @types package), then you will have to configure ESLint appropriately to define these global types. For example; the JSX namespace from @types/react is a global 3rd party type that you must define in your ESLint config.

Note, that for a mixed project including JavaScript and TypeScript, the no-undef rule (like any rule) can be turned off for TypeScript files alone as follows:

eslint.config.mjs
import tseslint from 'typescript-eslint';

export default tseslint.config(
// ... the rest of your config ...
{
files: ['**/*.{ts,tsx,mts,cts}'],
rules: {
'no-undef': 'off',
},
},
);

If you choose to leave on the ESLint no-undef lint rule, you can manually define the set of allowed globals in your ESLint config, and/or you can use one of the pre-defined environment (env) configurations.

I get errors from the @typescript-eslint/no-namespace and/or no-var rules about declaring global variables

Two common solutions in TypeScript for declaring the existence of a global variable include:

  • declare global with a var, which violates no-var:

    declare global {
    var myValue: string;
    // Unexpected var, use let or const instead. eslint (no-var)
    }

    myValue;
  • declare namespace globalThis, which violates @typescript-eslint/no-namespace:

    declare namespace globalThis {
    // ES2015 module syntax is preferred over namespaces. eslint (@typescript-eslint/no-namespace)
    let myValue: string;
    }

    globalThis.myValue;

Using global variables is generally discouraged. If possible, it's best to avoid declaring globals altogether.

If you absolutely must use one of the two strategies, then you can use an ESLint configuration comment to disable rules as needed. For example:

declare global {
// eslint-disable-next-line no-var -- Provided by an old third-party integration.
var myValue: string;
}
tip

Whenever you need to disable an ESLint rule, it's best to include an informative comment explaining why.

See #9582 and #7941 for discussions around typescript-eslint supporting these use cases.

Can I use ESLint's --cache with typescript-eslint?

ESLint's --cache option caches on a per-file basis. You can use it, but it will only work reliably for untyped rules -- and even then, not always.

Any ESLint rule that checks logic across files, including many rules from eslint-plugin-import, creates cross-file dependencies. Typed lint rules almost always have dependencies on types across files in practice. ESLint's caching doesn't account for those cross-file dependencies.

We don't recommend using --cache.