R

@robonen/tsconfig

Shared, strict TypeScript configurations — a small set of layered presets you extend instead of copying compiler options between packages.

Every package in a monorepo wants the same modern, strict TypeScript baseline, but keeping a dozen tsconfig.json files in sync by hand drifts almost immediately. @robonen/tsconfig ships one carefully tuned base config and three environment layers — dom, vue, and node — that extend it. Point your package's extends at the right preset and you inherit a consistent, bundler-first, type-check-only setup with no local compiler options to maintain.

Layered presets

basedomvue, plus a sibling node layer. Extend the one that matches the environment; everything else is inherited.

Strict by default

strict plus noUncheckedIndexedAccess, noImplicitOverride, noImplicitReturns and noFallthroughCasesInSwitch are on out of the box.

Bundler-first

module: Preserve with Bundler resolution, verbatimModuleSyntax and isolatedModules. Emit is noEmit — declarations come from tsdown.

Env isolation

Browser src (DOM, no Node globals) and tooling files (node types, no DOM) split into separate projects wired with project references.

Install

Add the package as a dev dependency. It ships only JSON presets — no runtime code.

sh
pnpm add -D @robonen/tsconfig

Usage

Pick the preset that matches the package and extend it from your tsconfig.json:

json
// Node / isomorphic library
{ "extends": "@robonen/tsconfig/tsconfig.base.json" }

Vue SFC packages extend the vue layer (adds jsx: preserve and strict vueCompilerOptions) and can declare path aliases inline:

json
// Vue package, with path aliases
{
  "extends": "@robonen/tsconfig/tsconfig.vue.json",
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

Note: path aliases resolve relative to the tsconfig.json location — baseUrl is intentionally omitted (deprecated, removed in TypeScript 7.0).

DOM + Node split

Most packages mix browser src with Node tooling files (vite.config.ts, vitest.config.ts, tsdown.config.ts). Split them into two projects wired with references so src never sees Node globals and config files never see DOM, then type-check the whole package with tsc -b / vue-tsc -b:

json
// tsconfig.json — solution root
{
  "files": [],
  "references": [
    { "path": "./tsconfig.src.json" },  // extends tsconfig.dom.json
    { "path": "./tsconfig.node.json" }  // *.config.ts, types: ["node"]
  ]
}

Where to next

  • Presets — the full table of base, dom, vue and node, with what each layer adds.
  • Project references — the complete DOM + Node split with composite and tsBuildInfoFile wiring.
  • What's included — the exact compiler options the base preset turns on.
  • See the guide sections in the sidebar for each of the above.

@robonen/tsconfig

Shared TypeScript configurations.

Install

pnpm install -D @robonen/tsconfig

Presets

Preset Extends Use for
tsconfig.base.json Node / isomorphic libraries (lib: ESNext, no DOM)
tsconfig.dom.json base Browser libraries (adds DOM, DOM.Iterable)
tsconfig.vue.json dom Vue SFC libraries / apps (adds jsx, vueCompilerOptions)
tsconfig.node.json base Build/test tooling files (*.config.ts) — adds types: ["node"], no DOM
tsconfig.json base Default alias for base (bare @robonen/tsconfig import)

Usage

Pick the preset that matches the package and extend it:

// Node / isomorphic library
{ "extends": "@robonen/tsconfig/tsconfig.base.json" }
// Browser library
{ "extends": "@robonen/tsconfig/tsconfig.dom.json" }
// Vue package, with path aliases
{
  "extends": "@robonen/tsconfig/tsconfig.vue.json",
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

Path aliases resolve relative to the tsconfig.json location — baseUrl is intentionally omitted (deprecated, removed in TypeScript 7.0).

Project references (DOM + Node split)

Most packages contain two environments: browser/library src (DOM) and Node tooling files (vite.config.ts, vitest.config.ts, tsdown.config.ts). They are split into separate projects wired with references, so src never sees Node globals and config files never see DOM:

// tsconfig.json — solution root, tools (tsdown/vitest/editor) target src below
{
  "files": [],
  "references": [
    { "path": "./tsconfig.src.json" },
    { "path": "./tsconfig.node.json" }
  ]
}
// tsconfig.src.json — the library code
{
  "extends": "@robonen/tsconfig/tsconfig.dom.json",
  "compilerOptions": {
    "composite": true,
    "types": [],
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.src.tsbuildinfo"
  },
  "include": ["src/**/*.ts"]
}
// tsconfig.node.json — build/test tooling files
{
  "extends": "@robonen/tsconfig/tsconfig.node.json",
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo"
  },
  "include": ["*.config.ts"]
}

Type-check the whole package (both projects) with tsc -b / vue-tsc -b. Point tsdown at the src project (tsconfig: './tsconfig.src.json') since the root has no compilerOptions.

What's included (base)

  • Target / Module: ESNext with module: Preserve + Bundler resolution
  • Strict mode: strict, noUncheckedIndexedAccess, noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch, noUncheckedSideEffectImports
  • Module safety: verbatimModuleSyntax, isolatedModules, moduleDetection: force
  • Type-check only: noEmit (declarations/output are produced by tsdown)
  • Interop: esModuleInterop, resolveJsonModule