npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ts7-eslint

v0.2.0

Published

Type-aware ESLint for TypeScript 7, the native Go port

Readme

ts7-eslint

Type-aware ESLint for TypeScript 7, the native Go port.

TypeScript 7 ships without a JavaScript compiler API. The typescript package exports only ./unstable/*, its root export is a version stub, and everything built on ts.createProgram and ts.TypeChecker stopped working with it. @typescript-eslint declares typescript: ">=4.8.4 <6.1.0" and refuses at import:

typescript-eslint does not support TS 7.0.

This rebuilds the layers that touched the compiler, on top of typescript/unstable/*, and runs the published rules unmodified. All 134 of them execute against the real TypeScript 7 checker.

Upstream tracks TypeScript 7 in #10940. Their reason for waiting, that a project with their compatibility obligations should not build on an API named unstable, is a good one. This is the experiment that issue invites.

Install

npm install --save-dev ts7-eslint eslint typescript@7

Node 22.15 or newer, for module.registerHooks. @typescript-eslint/eslint-plugin comes with it, and should not be installed separately: it has to be loaded after the resolution hook, which is what the entry point does.

npm prints peer warnings on install, because @typescript-eslint/[email protected] declares typescript: ">=4.8.4 <6.1.0" and this installs TypeScript 7. The resolution is correct, a single TypeScript on disk with no nested copy, but it fails under --strict-peer-deps. Silence it with:

{ "overrides": { "@typescript-eslint/parser": { "typescript": "$typescript" } } }

Usage

// eslint.config.mjs
import tseslint from "ts7-eslint";

export default tseslint.config(tseslint.configs.recommendedTypeChecked);

tseslint.configs also has base, recommended, strict, strictTypeChecked, stylistic and stylisticTypeChecked. The parser uses the nearest tsconfig.json above each file; to name one explicitly, add a config object of your own:

export default tseslint.config(tseslint.configs.recommendedTypeChecked, {
  languageOptions: {
    parserOptions: { project: "./tsconfig.json", tsconfigRootDir: import.meta.dirname },
  },
});

Upstream's typescript imports are redirected at runtime by a hook scoped to modules under @typescript-eslint and ts-api-utils, so your own import ts from "typescript" still resolves to the real TypeScript 7 and nothing in package.json changes.

What is inside

One published package, five layers.

| Layer | Responsibility | | --- | --- | | ts-api | The only one that imports typescript/unstable/*. Owns the program and checker, and restores the TypeScript 6 object model over TypeScript 7's handles | | typescript-estree | TypeScript AST to TSESTree, with tokens and comments rebuilt from the scanner | | parser | parseForESLint, and the parserServices rules expect | | ts-compat | The ts namespace upstream imports, 168 members | | resolution-hook | Points those imports at the shim, and nothing else's |

Nothing upstream is patched or forked. eslint-plugin, type-utils, utils, scope-manager, types and visitor-keys are the published 8.66.0 packages, used as they are.

Verification

pnpm test compares the AST against [email protected], the newest release the current stack supports, which keeps this a comparison of TypeScript 7 rather than of TypeScript versions. 23 fixtures match node for node, 1081 of 1081, along with every token and comment. The corpus deliberately includes constructs the converter was not written against: destructuring in every position, parameter properties, static blocks, tuple labels, type predicates, JSX, dynamic import(), and the comment traps.

node tools/bench/run.mjs lints five codebases with both stacks and compares every finding on rule, message and position.

| Corpus | Files | TS 6.0.3 | TS 7.0.2 | | Findings | Agreement | | --- | ---: | ---: | ---: | --- | ---: | ---: | | rxjs | 125 | 2.18 s | 1.47 s | 1.48x faster | 401 | 100.00% | | zod | 118 | 4.40 s | 4.64 s | 1.06x slower | 2434 | 100.00% | | ts-pattern | 18 | 0.77 s | 0.48 s | 1.61x faster | 266 | 100.00% | | app-backend | 295 | 6.42 s | 7.03 s | 1.09x slower | 2096 | 100.00% | | app-frontend | 416 | 2.54 s | 2.19 s | 1.16x faster | 558 | 100.00% | | total | 972 | 16.30 s | 15.81 s | 1.03x faster | 5686 | 100.00% |

Every finding agrees, 0 disagreements in 5,686, across generic-heavy library code, type-level metaprogramming, a React frontend, and an application backend with 1,400 tests. The last two are a private codebase, so the benchmark reads its location from TS7_ESLINT_APP_CORPUS and leaves them out when that is not set.

Speed

The 10x in the TypeScript 7 announcement is a whole-program build: one question, then Go working in parallel. A linter is the opposite shape of workload. It asks hundreds of thousands of small questions, one AST node at a time, each a synchronous round trip over a pipe, and about half of that time is transport rather than compilation.

So the cost model is the number of questions, and that is where the work went. On the 295-file backend the first working version made 664,000 round trips; it now makes 106,000, by memoising what the compiler asks itself, batching a file's nodes into one request, and not asking questions whose answer is already known. Shortcuts of that last kind are checked rather than argued: TS7_ESLINT_VERIFY=1 asks the compiler anyway and compares the two answers by identity.

What is left is 3.4 s of round trip on that corpus, 1.8 s of it the compiler computing. The rest is the pipe, and it is why two of the five corpora are still slower.

Limitations

  • A tsconfig.json is required. TypeScript 7 has no standalone parser, since an AST can only come from a program, so there is no project-less mode.
  • getAwaitedType is reimplemented, because neither TypeScript 7.0 nor the 7.1 development builds have it. A union mixing promises and non-promises comes back unchanged, as the API offers no way to construct a union type.
  • getChildren is reconstructed from the scanner. ESLint does not read it; 21 of 26 fixtures reproduce TypeScript 6.0.3 exactly and the rest differ only where the two parsers themselves do.
  • Message text can order union members differently, since TypeScript 7 prints types in its own order. Same rule, same location, same finding: string | (string | Query)[] | Query where TypeScript 6 wrote string | Query | (string | Query)[]. Anything snapshotting lint output will see that churn.
  • A type query the compiler cannot answer is reported as unknown rather than ending the run, and the first one prints a warning. typescript-go panics on a few type shapes, and losing every other file's findings to one of them is the worse failure.
  • typescript/unstable/* will change. Every import of it lives in one layer.

License

MIT