Active Foundation

Search documentation

Search all pages, headings and text, in the current package or topic or in all documentation.

Extending

How extends combines the presets with your own tsconfig, and where files, paths, environments and frameworks are set.

@workspace/typescript-config 1.0.0Developmentunreleased, maintained in Foundation as a copy

How extends works here#

"extends": "@workspace/typescript-config/nodejs.json" is resolved like a package import: from the folder of your tsconfig.json upwards to node_modules/@workspace/typescript-config, which pnpm links to your copy in packages/typescript-config. That is why the package is declared and installed (see Getting started). The package has no exports map; the four file names are its whole surface.

TypeScript then reads three layers, each over the previous one:

  1. base.json;

  2. the preset you extend;

  3. your own tsconfig.json.

Two rules decide the result:

  • A setting is replaced as a whole. compilerOptions merge key by key, but an array such as lib, types or plugins is not merged: yours replaces the inherited one. To add a type package to nodejs.json, restate node:

    JSON
    {  "extends": "@workspace/typescript-config/nodejs.json",  "compilerOptions": {    "types": ["node", "vitest/globals"]  },  "include": ["src"]}

    Without node, the result is "types": ["vitest/globals"] only, and process is unknown.

  • Paths are relative to the file that sets them. include, exclude, outDir, rootDir and paths in your tsconfig.json are resolved from your folder. The presets set none of them.

What you add#

ConcernWhereExample
which filesinclude, exclude"include": ["src"], "exclude": ["node_modules", "dist"]
outputnoEmit, or outDir and rootDir"noEmit": true; or "outDir": "dist", "rootDir": "src"
import aliasespaths"paths": {"@/*": ["./*"]}
environmenttypes"types": ["node"] for Node globals outside nodejs.json
test globalstypes, with what the preset already had"types": ["node", "vitest/globals"]
frameworkthe preset, plus the framework's own filesnextjs.json with next-env.d.ts in include
editor pluginsplugins, restating the preset's"plugins": [{"name": "next"}]

These are the additions the shared standard allows (docs/standards/CONFIG_STANDARDS.md § 3 in your copy of the standards): include, exclude, outDir, rootDir, paths, noEmit, types and plugins.

Re-declaring lib is possible but almost never needed: the base already carries the shared set, and a local copy drifts from it.

What you do not change#

Do not relax strict, noUncheckedIndexedAccess, target, moduleResolution or declaration. They are the guarantees every package of the Active packages is written against. A repository that must deviate records that as a decision in its own docs/DECISIONS.md, with its reason; a deviation that would serve every repository is proposed to the maintainer of Foundation instead.

Do not edit the copy in packages/typescript-config. A preset change is made in Foundation, with a changelog entry, and reaches every repository with the next copy.

Packages that travel to other repositories#

A package that is itself handed to other repositories (such as active-format and active-ui) does not extend this configuration. A bundler in the receiving repository reads the tsconfig.json of every source file it compiles, and a path to a preset that the receiver may not have would break that. Such a package carries a self-contained tsconfig.json with the values of the preset at the time it was written. Your own apps and packages extend the presets.

This page as Markdown