关于 shared-tooling-typescript-config
为 TypeScript 项目提供严格配置与共享 tsconfig 模式的实践指南,适用于新建或维护项目的开发者。内容涵盖现代模块选项、路径别名同步及不同项目类型的配置取舍。
主要功能
- 01严格类型检查选项
- 02单仓库共享配置模式
- 03现代模块解析设置
- 04跨配置同步路径别名
- 05TS 5.x 与 6.0 选项指导
适用场景
- 01为新项目启用严格模式
- 02统一单仓库各包的 tsconfig
- 03配置基于打包器的模块设置
- 04迁移弃用选项并评估新特性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agents-inc/ skills --skill shared-tooling-typescript-config安装后在 Claude Code 中输入/shared-tooling-typescript-config确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.yamlreference.mdexamples/core.md详细介绍
TypeScript 配置模式
快速指南: 在
packages/typescript-config/中使用共享的 TypeScript 严格配置。启用strict: true,以及noUncheckedIndexedAccess、exactOptionalPropertyTypes、noImplicitOverride。使用现代模块设置:module: "preserve"、moduleResolution: "bundler"、verbatimModuleSyntax: true、moduleDetection: "force"。使用${configDir}(TS 5.5+)设置可移植路径。在 tsconfig 和构建工具之间同步路径别名。
<critical_requirements>
重要:使用此技能前
(你必须在所有 tsconfig.json 文件中启用 TypeScript 严格模式(strict: true),这是不可妥协的要求)
(你必须使用 verbatimModuleSyntax: true 来强制显式使用 import type,以取代已弃用的 importsNotUsedAsValues)
(在 monorepo 中,你必须使用共享配置模式(packages/typescript-config/),绝不能为每个包重复配置)
(你必须在 tsconfig.json 和构建工具之间同步路径别名,不匹配会导致导入解析失败)
(对于基于打包工具的项目,你必须使用现代模块设置:module: "preserve"、moduleResolution: "bundler")
</critical_requirements>
自动检测: TypeScript 配置、tsconfig.json、tsconfig、严格模式、noUncheckedIndexedAccess、exactOptionalPropertyTypes、verbatimModuleSyntax、moduleDetection force、module preserve、moduleResolution bundler、configDir、路径别名、typescript-config、共享配置、noImplicitOverride、isolatedDeclarations、erasableSyntaxOnly、import defer
适用场景:
- 在新项目或现有项目中设置 TypeScript 严格模式
- 创建共享 tsconfig 模式,确保 monorepo 配置一致
- 配置 TS 5.x+ 现代模块设置(preserve、bundler、verbatimModuleSyntax)
- 在 tsconfig 和构建工具之间同步路径别名
- 创建专用配置(React、Node.js、库发布)
- 从已弃用的 TypeScript 选项迁移
- 评估新的 TS 特性(
isolatedDeclarations、erasableSyntaxOnly、configDir、import defer)
不适用场景:
- TypeScript 运行时代码模式(请参阅语言/框架相关技能)
- Linter 配置(请使用单独的技能)
- 构建工具配置(请使用单独的技能)——但此处仍应保留路径别名同步指南
- 命名和导入等日常编码规范(请参阅 CLAUDE.md)
涵盖的核心模式:
- 用于 monorepo 扩展模式的共享严格配置基准
- 现代模块设置(TS 5.x+:preserve、bundler、verbatimModuleSyntax、moduleDetection)
- 用于可移植共享配置的
${configDir}模板变量(TS 5.5+) - tsconfig 与构建工具之间的路径别名同步
- 专用配置(react.json、node.json、library.json)
- 用于支持并行构建的
isolatedDeclarations(TS 5.5+) - 用于 Node.js 直接执行的
erasableSyntaxOnly(TS 5.8+) - 用于延迟模块求值的
import defer(TS 5.9+) - TypeScript 6.0 的新默认值和弃用项
详细资源:
- examples/core.md - 完整配置示例、专用配置、TS 5.x+ 特性
- reference.md - 决策框架、反模式、注意事项
理念
TypeScript 配置应当默认严格、在各个包之间共享,并能面向未来。每个项目都从最严格的设置开始。共享配置可避免偏移。现代模块设置与基于打包工具的工作流保持一致。
核心原则:
- 默认严格 -
strict: true,以及noUncheckedIndexedAccess、exactOptionalPropertyTypes、noImplicitOverride - 共享而非重复 - Monorepo 配置扩展共享基准;独立项目使用相同的严格选项
- 现代模块模式 - 对于打包工具项目,使用
module: "preserve"+moduleResolution: "bundler";对于 Node.js,使用"node18"/"node20" - 路径别名一致 - 别名必须同时存在于 tsconfig 和构建工具中
核心模式
模式 1:共享严格配置基底
所有应用和包都扩展共享的严格基底。基底配置位于 packages/typescript-config/(单仓库)中,或内联在独立项目中。
// packages/typescript-config/base.json (abbreviated)
{
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"module": "preserve",
"moduleResolution": "bundler",
"verbatimModuleSyntax": true
}
}
使用方配置扩展共享基底,并且只添加有差异的内容(例如 paths)。
优点: 严格设置只有一个事实来源,所有包都能获得相同的安全保障,使用方只需添加有差异的内容
完整的基底配置、使用方配置和专用配置(react.json、node.json、library.json)请参见 examples/core.md。
模式 2:现代模块设置(TS 5.x+)
verbatimModuleSyntax(TS 5.0+)
强制对仅用于类型的导入显式使用 import type。替代已弃用的 importsNotUsedAsValues 和 preserveValueImports。
// With verbatimModuleSyntax: true
// Good - explicit type import
import type { User } from "./types";
import { createUser } from "./api";
// Bad - type imported as value (errors with verbatimModuleSyntax)
import { User, createUser } from "./api";
module: "preserve"(TS 5.4+)
原样保留导入/导出语法。TypeScript 只进行类型检查;模块输出由打包工具处理。
适用场景: 基于打包工具的项目,其中 TypeScript 不会生成 JavaScript(noEmit: true)
不适用场景: 直接生成 CJS/ESM 的 Node.js 包——改用 module: "node18" 或 "node20"
moduleDetection: "force"(TS 5.0+)
强制将所有文件视为模块,即使没有 import/export。防止意外污染全局作用域。
模式 3:${configDir} 模板变量(TS 5.5+)
使共享配置具有可移植性。${configDir} 会解析为叶级配置(即扩展其他配置的配置文件)所在目录,而非基底配置所在目录。
// packages/typescript-config/base.json
{
"compilerOptions": {
"outDir": "${configDir}/dist",
"rootDir": "${configDir}/src"
},
"include": ["${configDir}/src"]
}
优点: 使用方无需覆盖 outDir、rootDir 或 include——路径会相对于其自身目录解析
注意事项: 如果不使用 ${configDir},像 "./dist" 这样的相对路径会从基底配置所在位置(packages/typescript-config/)解析,而非从使用该配置的包解析。
模式 4:路径别名同步
路径别名必须同时配置在 tsconfig.json 和构建工具中。不匹配会导致 TypeScript 错误或构建时导入解析失败。
// tsconfig.json -- paths here for TypeScript type checking
{ "compilerOptions": { "paths": { "@/*": ["./src/*"] } } }
// Build tool config -- SAME aliases for bundler resolution
// resolve: { alias: { "@": path.resolve(__dirname, "./src") } }
注意事项: 忘记同步会导致“找不到模块”错误。TypeScript 可以正常解析,但打包工具会失败(反之亦然)。添加新别名时,务必同时更新两个文件。
完整的 tsconfig 和构建工具配置示例请参见 examples/core.md。
模式 5:isolatedDeclarations(TS 5.5+)
要求为所有导出显式添加类型注解。支持外部工具(oxc、swc)并行生成 .d.ts。
// With isolatedDeclarations: true
// Good - explicit return type on export
export function getUser(id: string): User {
return { id, name: "John" };
}
// Bad - inferred return type (will error)
export function getUser(id: string) {
return { id, name: "John" };
}
适用场景: 发布库包的大型单仓库项目,在这些项目中,并行生成 .d.ts 可加快构建速度
不适用场景: 永远不会作为库使用的应用代码(只会增加冗长程度,没有实际收益)
模式 6:erasableSyntaxOnly(TS 5.8+)
禁止具有运行时行为的 TypeScript 专属构造(枚举、命名空间、参数属性)。确保兼容 Node.js --experimental-strip-types,以便直接执行 TS。
禁止的构造: enum、const enum、运行时 namespace、参数属性(constructor(public name: string))
允许的构造: type、interface、仅用于类型的导入——任何可擦除且不会改变运行时行为的内容
适用场景: 使用 Node.js 直接执行 TS 的项目,或采用仅类型理念的项目
不适用场景: 严重依赖枚举、命名空间或参数属性的项目
完整的正反例代码请参见 examples/core.md。
模式 7:import defer(TS 5.9+)
延迟模块求值——模块会加载,但只有在访问某个导出时才会执行。仅在 --module preserve 或 esnext 下与命名空间导入搭配使用。
import * as analytics from "./heavy-analytics.js";
// Module is loaded but NOT executed yet
if (needsAnalytics) {
analytics.track("event"); // Module executes here on first access
}
适用场景: 提升有条件加载的重型模块的启动性能
限制: import defer 不支持命名导入和默认导入——只能使用命名空间语法(import defer * as ...)
模式 8:TypeScript 6.0 新默认值
TS 6.0(2026 年 2 月)调整了多个默认值。如果你的配置已遵循上述模式,大多数改动都不会产生影响。
| 选项 | 旧默认值 | TS 6.0 默认值 |
|---|---|---|
strict | false | true |
module | commonjs | esnext |
target | es3 | es2025 |
rootDir | 推断 | .(当前目录) |
types | 自动发现 @types/* | [](仅显式指定) |
noUncheckedSideEffectImports | false | true |
libReplacement | true | false |
需要采取的操作: 升级到 TS 6.0 后,显式设置 "types": ["node"](或相关包)——自动发现 @types/* 的功能已移除。
TS 6.0 中已弃用(将在 TS 7.0 中移除):
target: "es5"、moduleResolution: "node"(node10)、module: "amd"|"umd"|"systemjs"|"none"esModuleInterop: false、将--baseUrl用作模块解析根目录、--outFile
迁移期间使用 "ignoreDeprecations": "6.0" 可抑制警告。
完整的 TS 6.0 默认值表及弃用详情,请参阅 examples/core.md。
模式 9:NoInfer 工具类型(TS 5.4+)
防止 TypeScript 在泛型函数的特定位置推断类型。
// Good - NoInfer ensures initial must be from states array
declare function createFSM<TState extends string>(config: {
initial: NoInfer<TState>;
states: TState[];
}): void;
createFSM({
initial: "invalid", // Error: "invalid" not in states
states: ["open", "closed"],
});
优点: TypeScript 只会从 states 推断 TState;initial 必须匹配,但不会扩大联合类型
适用场景: 一个参数应约束另一个参数,而不是扩大推断类型的泛型函数
<decision_framework>
决策框架
模块设置选择
What module/moduleResolution to use?
├─ Bundler-based project (TypeScript does NOT emit JS)?
│ └─ YES -> module: "preserve", moduleResolution: "bundler"
├─ Node.js package (direct execution)?
│ ├─ Node 20+? -> module: "node20" (TS 5.9+, stable)
│ └─ Node 18+? -> module: "node18" (TS 5.8+)
└─ Library consumed by both bundlers and Node?
└─ module: "nodenext" (most compatible)
Target 选择
What target to use?
├─ Bundler-based project? -> target: "ES2022" (stable, well-supported)
├─ Node.js 18+? -> target: "ES2022"
├─ Node.js 20+? -> target: "ES2023"
└─ TS 6.0+ project? -> target: "es2025" (new default)
新功能采用
isolatedDeclarations?
├─ Publishing library packages in large monorepo? -> Enable
├─ Application code only? -> Skip (adds verbosity for no benefit)
└─ Using oxc or swc for builds? -> Enable (these tools benefit most)
erasableSyntaxOnly?
├─ Using Node.js --experimental-strip-types? -> Enable (required)
├─ Project uses enums extensively? -> Skip (migration cost too high)
└─ Standard bundler project? -> Optional (nice-to-have)
其他决策框架(共享配置与本地配置、TS 6.0 迁移)请参阅 reference.md。
</decision_framework>
<red_flags>
危险信号
高优先级问题:
- 禁用 TypeScript 严格模式(
strict: false)——会导致整个项目中出现隐式 any 和 null 相关错误 - 缺少
verbatimModuleSyntax: true——类型导入是否会被移除取决于转译器 - 在 monorepo 中未使用共享配置——配置会逐渐偏离,导致各个包的安全级别不一致
- 使用已弃用的
importsNotUsedAsValues或preserveValueImports——自 TS 5.0 起已由verbatimModuleSyntax取代
中优先级问题:
- 在 tsconfig 中配置了路径别名,却未在构建工具中配置(或反之)——会导致导入解析失败
- 使用已弃用的
moduleResolution: "node"(node10),而非"bundler"或"node18"——在 TS 6.0 中已弃用 - 使用已弃用的
target: "ES3"或"ES5"——在 TS 6.0 中已弃用,并将在 TS 7.0 中移除 - 每个包都重复配置,而非继承共享基础配置
注意事项与边缘情况:
${configDir}解析为叶级配置(即使用extends的配置)所在目录,而非基础配置所在目录verbatimModuleSyntax要求所有仅用于类型的导入都使用import type——如果Type仅用于类型,混合导入(如import { Type, value })会报错。请使用内联语法:import { type Type, value }exactOptionalPropertyTypes表示{ key?: string }不接受{ key: undefined }——只能省略该属性或使用stringnoUncheckedIndexedAccess会为所有索引签名(包括数组)添加| undefined——请使用for...of或通过if进行保护module: "preserve"仅适用于noEmit: true或emitDeclarationOnly: true- TS 6.0 会将
types的默认值改为[]——升级后必须显式列出@types/node、@types/react等 import defer仅支持命名空间语法(import defer * as ...),不支持命名导入或默认导入
</red_flags>
<critical_reminders>
重要提醒
(必须在所有 tsconfig.json 文件中启用 TypeScript 严格模式(strict: true),此项不可妥协)
(必须使用 verbatimModuleSyntax: true 强制显式使用 import type,它已取代弃用的 importsNotUsedAsValues)
(在 monorepo 中必须使用共享配置模式(packages/typescript-config/),绝不可为每个包重复配置)
(必须确保 tsconfig.json 与构建工具中的路径别名保持一致——不一致会导致导入解析失败)
(必须使用现代模块设置:基于打包器的项目应使用 module: "preserve"、moduleResolution: "bundler")
不遵守这些规则会导致类型安全漏洞、配置不一致以及导入解析失败。
</critical_reminders>