xo icon indicating copy to clipboard operation
xo copied to clipboard

enabled @typescript-eslint rules crash xo with TypeError when targeting js files (version 1.0.0+)

Open meszaros-lajos-gyorgy opened this issue 7 months ago • 4 comments

Hi! Did a bit of testing with the new flat config in the latest v1.0.4 and as the title says: @typescript-eslint rules that are not set to "off" are not ignored for configs targetting .js files, but outright crash xo with an uncaught TypeError.

Here's the simplest config I could come up with to be able to reproduce the issue with:

// xo.config.ts - rule enabled, without js -> no error
import type { FlatXoConfig } from 'xo'

const xoConfig: FlatXoConfig = {
  space: true,
  semicolon: false,
  prettier: true,
  files: '**/*.{ts}', // <---- can also be {ts,tsx} or simply ts, all behave the same here
  rules: {
    '@typescript-eslint/naming-convention': [
      'error',
      {
        selector: 'variable',
        format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
      },
    ],
  },
}

export default xoConfig

This config runs correctly, files get linted.

If I introduce js extension to the files, like **/*.{js,ts} or **/*.{js},then running xo will start running and - presumably when it reaches an actual js file - throws the following error:

// xo.config.ts - rule enabled, with js -> error
import type { FlatXoConfig } from 'xo'

const xoConfig: FlatXoConfig = {
  space: true,
  semicolon: false,
  prettier: true,
  files: '**/*.{ts,js}',
  rules: {
    '@typescript-eslint/naming-convention': [
      'error',
      {
        selector: 'variable',
        format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
      },
    ],
  },
}

export default xoConfig

Image

The same happens with any @typescrip-eslint rule as long as it's not turned off with the "off" value.

Having the rule turned off doesn't produce any errors:

// xo.config.ts - rule disabled, with js -> no error
import type { FlatXoConfig } from 'xo'

const xoConfig: FlatXoConfig = {
  space: true,
  semicolon: false,
  prettier: true,
  files: '**/*.{ts,js}',
  rules: {
    '@typescript-eslint/naming-convention': 'off'
  },
}

export default xoConfig

With the old config prior to version 1.0.0 this isn't an issue.

meszaros-lajos-gyorgy avatar May 30 '25 23:05 meszaros-lajos-gyorgy

This might be loosly connected to https://github.com/xojs/xo/issues/496 as @typescript-eslint/naming-convention should work with js files as well.

meszaros-lajos-gyorgy avatar May 30 '25 23:05 meszaros-lajos-gyorgy

The difference comes from older versions of eslint and typescript-eslint. In xo v0, the config was more permissive and often ignored typescript-eslint rules on JS files—even when explicitly set.

In v1, we load the typescript-eslint plugin only for TS files. If you include "files" prop, we respect it exactly; if not, we apply the typescript-eslint rules to the TS config automatically. By adding files prop, you're opting into manual control and then its up to eslint to throw or not.


One idea: use typescript-eslint as the parser for all files.

Pros: Uniform rule behavior across JS and TS

Cons: Slight performance hit in JS-heavy projects

We could make this opt-in via a flag like tsForJs?

@sindresorhus thoughts on the following xo options?

Add a flag to let users apply typescript-eslint and xo-typescript rules to JS files

Use TS parser for all files by default (non-optional), applying standard JS rules and TS rules when configured

Or a mix of both—or neither?

spence-s avatar Jun 10 '25 00:06 spence-s

@spence-s Could XO check if typescript-eslint rules are being applied to JS files, and use the TS parser for all files in only those cases, or maybe use the TS parser for just those specific files?

som-sm avatar Jun 10 '25 11:06 som-sm

@spence-s Could XO check if typescript-eslint rules are being applied to JS files, and use the TS parser for all files in only those cases, or maybe use the TS parser for just those specific files?

Yeah this might be a nice solution:

  1. check that the config does not have a custom parser
  2. check that it has tsrules turned on that could be applied to js files
  3. apply ts parsing to those files

I think something like that might work well and it would avoid adding more options to configs and it would only incur minimal performance penalties based on the users options.

spence-s avatar Jun 10 '25 13:06 spence-s

I think something like that might work well and it would avoid adding more options to configs and it would only incur minimal performance penalties based on the users options.

👍

sindresorhus avatar Jun 20 '25 22:06 sindresorhus