@aleph-alpha/tsconfig-frontend

中文文档
0.7.3发布于 2026/08/11Apache-2.0ES Module近 30 天下载 1.4万

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

原始使用文档
文档目录9 节
  1. Why four presets instead of one?
  2. Presets at a glance
  3. /base
  4. /vue-app
  5. /lib
  6. /node
  7. What the package owns vs. what the project owns
  8. Why the presets are self-contained
  9. Common overrides & gotchas

@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

PresetExtendsUse it forEmits?
/base—Framework-agnostic TS: shared libs, utils, pure logicno
/vue-app— (mirrors @vue/tsconfig)Vue SFCs & browser code (apps and Vue component libs)no (Vite/dts plugin emits)
/lib./baseBuildable libraries that emit .d.ts via tscyes
/node— (mirrors @tsconfig/node24)Node tooling: vite.config, vitest.config, eslint.config, scriptsno

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. Mirrors the Vue team's official @vue/tsconfig/tsconfig.dom.json, inlined verbatim rather than extended (see Why the presets are self-contained).

Sets (on top of the inlined @vue/tsconfig baseline, 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. Mirroring @vue/tsconfig (rather than re-deriving it) gives us the Vue team's battle-tested defaults; re-merge the upstream file by hand when bumping it.

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 (from the inlined baseline) 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 (on top of the inlined @tsconfig/node24 baseline):

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

Why — vite.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.

Why the presets are self-contained

No preset here extends a config from another package — /vue-app and /node inline their upstream baselines (@vue/tsconfig, @tsconfig/node24) instead of extending them.

TypeScript resolves a package-style extends the way Node resolves an import, walking up node_modules and following symlinks. Other tools that read tsconfig.json do not. Playwright, for one, looks only in <the extending file>/node_modules/… — so with pnpm, where a package's own dependencies live in the store rather than inside the package folder, it cannot follow node.json → @tsconfig/node24 and fails to load the config entirely:

Failed to load tsconfig file at …/apps/<app>-e2e/tsconfig.json:
Failed to resolve "extends" path "@tsconfig/node24/tsconfig.json"
referenced from …/node_modules/@aleph-alpha/tsconfig-frontend/node.json

Keeping every preset self-contained removes that whole class of failure — for Playwright and for any other tool with a naive resolver. The cost is that upstream bumps must be re-merged by hand; the provenance (package + exact version) is recorded in a "//" key at the top of each affected preset.

Relative extends within this package (/lib → ./base) is fine — every tool handles that.

@vue/tsconfig and @tsconfig/node24 remain in this package's dependencies even though no preset extends them anymore. That is deliberate: dropping them would break any consumer that extends either package directly and relies on it arriving transitively. They are kept for backwards compatibility and slated for removal in a future major — if you extend either one directly, declare it in your own package.json.

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.

版本与发布记录

@aleph-alpha/tsconfig-frontend 共发布 129 个版本,首次发布于 2025/03/10;过去 12 个月发布了 86 个版本。

版本发布日期距今
0.7.3latest2026/08/112 个月前
0.7.22026/08/102 个月前
0.7.12026/07/133 个月前
0.7.02026/06/025 个月前
0.6.02026/05/056 个月前
0.5.02025/12/1810 个月前

其他发布通道:canary → 0.3.2-canary.6a2fa49c.0。

关于 @aleph-alpha/tsconfig-frontend 的常见问题

@aleph-alpha/tsconfig-frontend 是什么?

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

如何安装 @aleph-alpha/tsconfig-frontend?

在项目目录运行 npm install @aleph-alpha/tsconfig-frontend,或使用 pnpm add / yarn add / bun add。

@aleph-alpha/tsconfig-frontend 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/aleph-alpha__tsconfig-frontend 是否存在。

@aleph-alpha/tsconfig-frontend 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aleph-alpha/tsconfig-frontend 可以商用吗?

@aleph-alpha/tsconfig-frontend 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@aleph-alpha/tsconfig-frontend 的下载量有多少?

根据 npm 官方下载统计,@aleph-alpha/tsconfig-frontend 在 2026/10/06 – 2026/11/04 这 30 天内被下载 14,119 次,日均约 471 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aleph-alpha/tsconfig-frontend 还在维护吗?

最新版本 0.7.3 发布于 2026/08/11(2 个月前);至今共发布 129 个版本,其中过去 12 个月发布了 86 个;首次发布于 2025/03/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。