Repository navigation
Migrate to ESLint 10 flat config and TypeScript 6 with strict mode - #31
Merged
Merged
Conversation
TypeScript 7 is out, but typescript-eslint supports only >=4.8.4 <6.1.0,
and TS 7's native port no longer exposes the compiler API it relies on.
6.0 is the latest release that lint can use.
TypeScript 6 changes several defaults:
- types defaults to [], so list node and mocha explicitly for their
globals (console, fs, describe, ...).
- strict defaults to true. Set it explicitly and fix the 19 errors it
reports, adding @types/proxyquire for the one untyped import.
- esModuleInterop defaults to true, and setting it to false is
deprecated. Namespace imports now go through __importStar, which
returns a plain object, so the proxyquire namespace import was no
longer callable ("pq is not a function"). Import it as a default
import instead.
Strict mode surfaced one real bug: running the ruby.packwerk command
with no active editor threw a TypeError. It now returns early. Other
fixes are type-only or equivalent for their callers: parse() returns
null rather than undefined for a non-SyntaxError, and Task.run()
returns a resolved promise for a cancelled task. The task error log now
passes the error itself, rather than logging its message twice.
ESLint 9 made flat config the default and ESLint 10 removed .eslintrc support entirely, so port .eslintrc.json to eslint.config.mjs. Replace @typescript-eslint/eslint-plugin and @typescript-eslint/parser with the typescript-eslint package, which bundles both. The resolved rule set matches the old config (compared via --print-config on a source and a test file), except for @typescript-eslint/no-var-requires. It is deprecated and fully covered by @typescript-eslint/no-require-imports, which was already enabled. The deprecated core formatting rules (max-len, quotes, semi, and so on) still work in v10 and are kept as-is. ESLint 9+ also reports unused eslint-disable directives as warnings by default; the codebase has none.
This was referenced Sep 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Handles the ESLint and TypeScript major versions that the grouped Dependabot PR #28 failed on. It has two commits, which can be reviewed separately.
TypeScript 5.9 → 6.0, with strict mode
This targets 6.0, not 7. typescript-eslint (latest 8.71.0) supports only
typescript >=4.8.4 <6.1.0, and TypeScript 7's native port no longer exposes the compiler API it relies on. The range is pinned to~6.0.3so it stays inside that range.TypeScript 6 changes several defaults, which
tsconfig.jsonnow handles:typesdefaults to[]: listsnodeandmochaexplicitly so their globals (console,fs,describe, …) resolve.strictdefaults totrue: sets it explicitly and fixes the 19 errors it reported. Also adds@types/proxyquire.esModuleInteropdefaults totrue, and setting it tofalseis deprecated. Namespace imports now compile to__importStar(require(...)), which returns a plain object. That brokeimport * as pq from 'proxyquire'at runtime (TypeError: pq is not a function), so it's now a default import. The other namespace imports (vscode,fs,path, …) are all used as objects and are unaffected.I compared the emitted JavaScript against main's TypeScript 5.9 build. Apart from the interop helpers, the only runtime changes are these:
ruby.packwerkwith no active editor now returns early. Before, it threw aTypeErrorthat VS Code reported as a command error. This is the one real bug strict mode found.parse()returnsnullinstead ofundefinedwhen it catches a non-SyntaxError. Its only caller treats the two the same.Task.run()returns a resolved promise instead ofundefinedfor a cancelled task. Its only caller awaits it.ESLint 8 → 10, flat config
ESLint 10 removed
.eslintrcsupport, so.eslintrc.jsonbecomeseslint.config.mjs.@typescript-eslint/eslint-pluginand@typescript-eslint/parserare replaced by thetypescript-eslintpackage, which bundles both.--print-configoutput on a source file and a test file. The rule names, severities and options match, except for@typescript-eslint/no-var-requires. It's deprecated and fully covered by@typescript-eslint/no-require-imports, which is already enabled.max-len,quotes,semi,no-trailing-spaces,no-multiple-empty-lines) still work in v10 and are unchanged. Moving them to@stylistic/eslint-plugincan be a follow-up.eslint-disabledirectives. The codebase has none.eslint.config.mjsis added to.vscodeignore.Testing
yarn install --frozen-lockfile,yarn run vscode:prepublishandyarn lintpass with no errors or warnings. All 13 tests pass locally.no-var,quotes,no-require-imports,semi,eqeqeq,curly,no-console,radixand the unused-directive check all fired.yarn auditshows only the existing low-severitydiff7.0.0 advisory, which Dependabot auto-dismissed (#40).Not in this PR
@types/sinon,@types/node26 and@types/vscode1.138..github/dependabot.ymlwould stop that.