enabled @typescript-eslint rules crash xo with TypeError when targeting js files (version 1.0.0+)
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
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.
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.
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 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?
@spence-s Could XO check if
typescript-eslintrules 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:
- check that the config does not have a custom parser
- check that it has tsrules turned on that could be applied to js files
- 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.
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.
👍