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

@williamthorsen/tsconfig

v0.10.0

Published

Shared TypeScript base config for Node-only projects

Readme

@williamthorsen/tsconfig

Shared TypeScript base config for Node-only projects. Inlines the settings of @tsconfig/strictest and adds the Node and build options that it leaves out, so a consuming repo declares only what is genuinely its own.

Release notes — v0.10.0 (2026-09-29)

🎉 Features

  • Rewords the messages that the package's ReadyUp kit reports: The redundant-option check is now named "No tsconfig re-declares an option that the base already supplies", and the fix hints for the redundant-option, ES-year, Node-floor, and escaping-path checks are reworded. (#250)

Installation

pnpm add -D @williamthorsen/tsconfig

Quick start

{
  "extends": "@williamthorsen/tsconfig/tsconfig.base.json",
  "compilerOptions": {
    "types": ["node"],
  },
  "include": ["src/"],
}

Adopting the base

Extend the base from every tsconfig in the repo, not from the root alone. A workspace config extends it either directly or through a config that does:

// packages/api/tsconfig.json
{
  "extends": "../../tsconfig.json",
  "include": ["src/"],
}

Every package whose tsconfig names the base by package specifier must also declare it as a devDependency: TypeScript resolves extends from the directory of the config that declares it, so a workspace naming a package on which it does not depend resolves nothing.

Once the base is in the chain, delete the options that it already supplies with the same value. The inherited value applies either way, and the copy left behind stops tracking the base the next time it changes. An option set to a different value is an override and stays.

A package that extends a framework base such as astro/tsconfigs/base or @tsconfig/svelte has opted out of this one, which is a supported choice.

What the base sets

Everything @tsconfig/strictest sets, plus the Node and build options it omits:

| Option | Value | | ---------------------------- | --------------------------------- | | allowImportingTsExtensions | true | | lib | ["ES2025", "ESNext.Disposable"] | | module | "NodeNext" | | moduleDetection | "force" | | noEmit | true | | removeComments | true | | target | "ES2025" |

target and lib are pinned to a Node 24 floor. ESNext.Disposable supplies the explicit-resource-management declarations (using, Disposable, DisposableStack), which Node 24 implements but the numbered libs do not yet include.

What the consumer owns

The base declares none of these:

  • types: The ambient type packages in scope. Most Node projects want ["node"]; declaring it narrows the default, which would otherwise pull in every @types/* package installed.
  • paths: TypeScript resolves baseUrl-less paths relative to the file that declares them, so a path alias set in this package would resolve inside node_modules. Aliases must be declared by the config that owns the source tree.
  • jsx: Meaningless for the many consumers with no JSX at all.

include and exclude are likewise the consumer's, since only it knows its own layout.

Emitting

The base sets noEmit: true, on the assumption that a separate build step owns emit. A consumer that builds with this config directly must override noEmit and, if it keeps allowImportingTsExtensions, pair that with rewriteRelativeImportExtensions so that ./foo.ts specifiers survive the rewrite.

Checking the configuration

This package ships a ReadyUp kit that checks whether the workspace tsconfigs are wired for the installed version. It is a migration aid rather than a CI gate: Only a Node floor too old to run the base's ES year is reported as an error, and everything else caps at a warning.

Run it once:

pnpm exec rdy run --from npm:@williamthorsen/tsconfig

Or list it in .config/readyup.config.ts to include it in every rdy run --packages:

import { defineRdyConfig } from 'readyup';

export default defineRdyConfig({
  packages: ['@williamthorsen/tsconfig'],
});

The readyup >=0.33.0 optional peer names the version against which the kit is developed and tested. Below 0.33.0, readyup does not report the repo root among a monorepo's workspaces, so the kit supplies the root itself and sweeps every member package alongside it.

The kit walks each workspace tsconfig's extends chain and reports five things:

  • Adoption: a tsconfig reaching neither this base nor a framework base. A tsconfig naming this base through a specifier that does not resolve is reported separately, as declared but not installed.
  • Re-declaration: an option restated with the base's own value. A key that a framework base in the same chain also declares is exempt, since restating it is how a config overrides that base.
  • Escaping paths: an include, exclude, or files path resolving outside the directory that holds the tsconfig. A config that is extended hands these fields down resolved against its own directory, so a package inheriting them is governed by paths pointing outside itself; the remedy is a complete local declaration, or ${configDir} in the config being extended.
  • ES year: a target or lib declaring a year other than the base's, read from the base that the tsconfig extends rather than from a constant compiled into the kit.
  • Node floor: an engines.node below the major that implements that ES year. This is the one failure that tsc cannot report on its own, which is why it alone is an error.

The kit runs at the version resolved from the project's node_modules, so it reports whether the configuration matches that version. It never reports whether that version is current.

License

ISC