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

@aleph-alpha/tsconfig-frontend

v0.7.0

Published

Shared strict TypeScript presets (base, vue-app, lib, node) for Aleph Alpha frontend projects

Readme

@aleph-alpha/tsconfig-frontend

Shared, strict-by-default TypeScript configuration for Aleph Alpha frontend projects.

It ships a small set of composable presets. The idea: everything that is genuinely shareable (language target, module resolution, the strict family, common quality flags) lives here in one reviewed place; everything project-specific (paths, include/exclude, emit layout, environment types) stays in the consuming project. Every compilerOption a preset sets can be overridden locally — presets are a baseline, not a straitjacket.

pnpm add -D @aleph-alpha/tsconfig-frontend

Why four presets instead of one?

base is the single extensible core. The other three exist because TypeScript compilation has distinct, mutually-exclusive contexts that one config cannot serve at once — and which every frontend project already separates (a tsconfig.app.json for browser code + a tsconfig.node.json for tooling is the de-facto standard):

  • Browser/Vue code needs DOM libs + JSX; Node tooling must not have them.
  • Node tooling needs types: ["node"]; browser code must not pollute its global scope with them.
  • Packages that emit .d.ts need declaration/composite; apps that don't emit would error on them.

Collapsing to one config wouldn't remove that configuration — it would just copy-paste it into every project (and invite mistakes like a too-low lib). The presets move it into one place.

Presets at a glance

| Preset | Extends | Use it for | Emits? | | --- | --- | --- | --- | | /base | — | Framework-agnostic TS: shared libs, utils, pure logic | no | | /vue-app | @vue/tsconfig | Vue SFCs & browser code (apps and Vue component libs) | no (Vite/dts plugin emits) | | /lib | ./base | Buildable libraries that emit .d.ts via tsc | yes | | /node | @tsconfig/node24 | Node tooling: vite.config, vitest.config, eslint.config, scripts | no |

The bare @aleph-alpha/tsconfig-frontend entry still resolves (it maps to the legacy flat config) for backwards compatibility. New code should extend one of the four presets above.


/base

What — the framework-agnostic strict baseline. No DOM, no Node, no JSX assumptions.

Sets (the shareable core all other presets build on conceptually):

{
  "target": "es2022",
  "module": "esnext",
  "moduleResolution": "bundler",
  "lib": ["es2022"],

  // strict family
  "strict": true,                     // implies noImplicitAny, strictNullChecks, ...
  "noUncheckedIndexedAccess": true,   // arr[i] / obj[key] is T | undefined
  "verbatimModuleSyntax": true,       // type-only imports must use `import type`
  "useDefineForClassFields": true,

  // safe bug-catchers (no emit impact, catch real bugs)
  "noImplicitOverride": true,         // overrides must be marked `override`
  "noFallthroughCasesInSwitch": true,
  "noImplicitReturns": true,

  // ergonomics
  "isolatedModules": true,
  "esModuleInterop": true,
  "forceConsistentCasingInFileNames": true,
  "importHelpers": true,
  "resolveJsonModule": true,
  "skipLibCheck": true,
  "sourceMap": true
}

Why — this is the strictness contract for the whole org. noUncheckedIndexedAccess and the bug-catchers catch real defects; verbatimModuleSyntax keeps imports unambiguous for bundlers.

When to use — pure TypeScript with no browser or Node assumptions (e.g. a utils package).

How to use

{
  "extends": "@aleph-alpha/tsconfig-frontend/base",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@/*": ["src/*"] }
  },
  "include": ["src/**/*.ts"]
}

/vue-app

What — config for Vue Single-File Components and browser code. Extends the Vue team's official @vue/tsconfig/tsconfig.dom.json, so it tracks upstream Vue/TS recommendations.

Sets (on top of @vue/tsconfig, which already provides strict, verbatimModuleSyntax, useDefineForClassFields, jsx: "preserve", jsxImportSource: "vue", noEmit):

{
  "lib": ["ES2022", "DOM", "DOM.Iterable"],
  "types": ["vite/client"],
  "noImplicitOverride": true,
  "noFallthroughCasesInSwitch": true,
  "noImplicitReturns": true
}

Why.vue files need JSX + DOM libs + Vue's jsxImportSource. Building on @vue/tsconfig (rather than re-deriving it) avoids drift and gives us the Vue team's battle-tested defaults.

When to use — any app or component library containing .vue files. The actual JS/.d.ts output is produced by Vite / vite-plugin-dts, not tsc — so noEmit: true (inherited) is correct here.

How to use

{
  "extends": "@aleph-alpha/tsconfig-frontend/vue-app",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@/*": ["src/*"] }
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}

/lib

What — for buildable library packages that emit type declarations through tsc.

Sets (extends ./base):

{
  "declaration": true,
  "composite": true,
  "lib": ["es2022", "dom", "dom.iterable"]
}

Why — emitting libraries need declaration (to ship .d.ts) and composite (project references / incremental builds). These would be wrong for apps, so they live in their own preset.

When — a non-Vue package whose .d.ts is produced by tsc (not by Vite). Typically paired with a local outDir/rootDir.

How

{
  "extends": "@aleph-alpha/tsconfig-frontend/lib",
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src",
    "paths": { "@/*": ["src/*"] }
  },
  "include": ["src/**/*.ts"]
}

Note: composite is incompatible with outFile. If a package bundles its declarations into a single file via outFile, extend /base instead and add declaration + emitDeclarationOnly locally (see the outFile gotcha below).


/node

What — config for Node-executed tooling files, not shipped browser code.

Sets (extends @tsconfig/node24):

{
  "noEmit": true,
  "module": "esnext",
  "moduleResolution": "bundler",
  "types": ["node"],
  "noImplicitOverride": true,
  "noFallthroughCasesInSwitch": true,
  "noImplicitReturns": true
}

Whyvite.config.ts, vitest.config.ts, eslint.config.ts, build scripts, etc. run in Node and need Node globals/types, not the DOM. Keeping them in a separate config means browser code never accidentally pulls in Node types and vice-versa.

When to use — the tsconfig.node.json that type-checks your config/tooling files.

How to use

{
  "extends": "@aleph-alpha/tsconfig-frontend/node",
  "include": ["vite.config.ts", "vitest.config.ts", "eslint.config.ts"]
}

What the package owns vs. what the project owns

In the presets (shareable): target, module/moduleResolution, baseline lib, the strict family, the bug-catchers, and the emit shape for /lib. Change these only by changing the package (so every consumer moves together).

In the project (always local & overridable): paths + baseUrl, include/exclude, rootDir/outDir/tsBuildInfoFile, environment types, references, experimentalDecorators/emitDecoratorMetadata, and any per-project strict opt-out/opt-in.

Common overrides & gotchas

These come up in real migrations — all are legitimate local overrides:

  • Need a newer JS built-in (Array.prototype.toSorted = ES2023, etc.)? @vue/tsconfig and our presets target a conservative lib. Bump it locally: "lib": ["ES2023", "DOM", "DOM.Iterable"]. This only affects type-checking — Vite controls the real browser target.
  • Code uses window/DOM but extends /base? Add DOM to lib locally: "lib": ["ES2022", "DOM"]. (Or use /vue-app, which includes DOM.)
  • outFile for a single bundled .d.ts? outFile is incompatible with both composite and verbatimModuleSyntax. Extend /base, set declaration + emitDeclarationOnly + outFile, and override "verbatimModuleSyntax": false locally.
  • Node tooling that isn't a config file (e.g. a Node-targeted library)? Extend /base and add "types": ["node"] rather than /node (which forces noEmit).
  • Migrating a codebase that predates noImplicitAny? If turning it on surfaces a large backlog, you may temporarily set "noImplicitAny": false locally and burn the errors down later — but keep it on in base so new/clean code stays strict.

Convention: document the reason for any strict opt-out in the PR description, not as a comment in the tsconfig — so it doesn't rot when the override is later removed.