关于 typescript-typecheck
typescript-typecheck 是帮助 TypeScript 项目配置独立类型检查门禁的技能,面向开发者及维护 CI 的团队。它用严格的 tsconfig、独立的 tsc 检查和项目引用补足仅转译代码的构建流程,并将检查接入 CI。
主要功能
- 01配置严格的 tsconfig
- 02建立独立 tsc 类型检查脚本
- 03设置 Vite 分离式配置
- 04为 monorepo 配置项目引用
- 05在 CI 中运行类型检查
适用场景
- 01为新 TypeScript 项目设置类型检查门禁
- 02检查 bundler 应用的模块解析配置
- 03让 CI 阻止类型错误通过
- 04检查 monorepo 跨包类型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bm629/ agent-skills --skill typescript-typecheck安装后在 Claude Code 中输入/typescript-typecheck确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ci-gate.mdproject-references.mdsources.mdstrict-tsconfig.mdvite-split-config.md详细介绍
typescript-typecheck — SKILL.md
**变体:**标准 · **使用时机:**调用此技能后,它会运行至完成,并返回配置好的类型检查门禁(tsconfig + 脚本 + CI 步骤),然后将控制权交还给调用方。
概述
TypeScript 编译器(tsc)是唯一真正执行类型检查的工具。典型 TS 工具链中的打包器和转译器——Vite(开发环境使用 esbuild,生产环境使用 Rollup)以及基于 SWC 的 React 插件——只会转译/移除类型注解,不会检查类型。这意味着,即使代码中充满类型错误,vite build(或任何 esbuild/SWC 构建)仍会成功编译。此技能用于补上缺失的环节:设置专用的 tsc --noEmit 类型检查门禁,在本地和 CI 中运行,并由真正严格的 tsconfig 提供支持;此外,还会配置 TypeScript 项目引用,以便在 monorepo 中解析跨包类型。这相当于单独的静态分析门禁:linter(Biome/ESLint)可以发现代码风格问题和 bug 模式,但没有类型系统,无法完成这项工作。适用于 TypeScript 5.x。经过验证的标志列表和示例见 references/。
何时启用
- ✅ 首次为项目设置 TypeScript 类型检查(
typecheck脚本 + CI 步骤)。 - ✅ 编写或收紧
tsconfig.json,并希望它真正严格(不只是设置strict: true)。 - ✅ 为 Vite/esbuild/打包器应用配置
moduleResolution: "bundler",并正确设置配套标志。 - ✅ 设置 TypeScript 项目引用(
composite、references、tsc -b),以便应用包在 monorepo 中使用库/生成包的类型。 - ✅ 添加 CI 类型检查门禁(例如使用 pnpm 的 GitHub Actions),让类型错误导致构建失败,即使打包器原本会忽略这些错误。
不要在以下情况启用:
- 任务涉及 lint/格式化规则——这是 linter 的工作(例如
biome技能);linter 不会执行类型检查。 - 任务涉及实际的生产打包/构建产物——这属于打包器的职责(例如
vite技能);此技能只负责tsc检查。 - 任务是深入讲解 TypeScript 类型系统(高级条件类型/映射类型、泛型技巧)——此技能关注的是门禁及其配置,而非类型理论。
- 任务涉及配置 monorepo 任务运行器的流水线/缓存——这属于任务运行器技能(例如
turborepo);此技能只负责提供它应运行的typecheck任务。
工作流
第 1 步:明确门禁为何独立存在(绝不要跳过)
理解这一点,并在相关配置中明确说明:没有任何转译器会执行类型检查。
- Vite 官方文档指出,它只会转译
.ts文件,不会执行类型检查,并假定“类型检查由 IDE 和构建流程负责”——因此明确建议加入tsc --noEmit步骤。esbuild“只执行转译,不提供类型信息”。 - 基于 SWC 的 React 插件(
@vitejs/plugin-react-swc)也一样:SWC 会移除类型,但不检查类型。选择 SWC 而非 Babel/esbuild 是由打包器配置决定的构建速度决策——它不会增加或移除类型检查;仍然需要tsc门禁。
结论:独立的 tsc --noEmit(或配合项目引用使用 tsc -b --noEmit)门禁是必需的,而非可选项,并且必须与 vite build 分开。
第 2 步:编写真正严格的 tsconfig
strict: true 是底线,而非上限。它会启用一组已知选项(完整列表和配置示例见 references/strict-tsconfig.md):
noImplicitAny、strictNullChecks、strictFunctionTypes、strictBindCallApply、strictPropertyInitialization、noImplicitThis、useUnknownInCatchVariables、alwaysStrict。
添加 strict 未涵盖的高价值选项:
noUncheckedIndexedAccess— 为索引/数组访问结果添加undefined(这是strict之外最能捕获真实错误的一项)。noImplicitOverride— 要求使用override关键字,避免子类在不知不觉中偏离父类。noFallthroughCasesInSwitch、noImplicitReturns— 确保控制流完整。noUnusedLocals、noUnusedParameters— 检查死代码(以_为前缀的参数除外)。exactOptionalPropertyTypes— 区分“缺省”和“设为undefined”(参见注意事项——添加此选项前应了解其影响)。verbatimModuleSyntax— 严格按照你写下的type修饰符移除导入/导出(不再猜测是否应省略)。
对于 Vite/打包器应用,模块配置块为:"module": "esnext"(或 "preserve")、"moduleResolution": "bundler"、"noEmit": true、"jsx": "react-jsx"、"isolatedModules": true、"moduleDetection": "force"。设置严格底线最简单的方法是:先配置 "extends": "@tsconfig/strictest",再叠加打包器配置块。
第 3 步:采用 Vite 的拆分配置布局(如果使用 Vite)
Vite TS 应用会生成三个文件:只包含 "files": [] 和指向两个叶子配置的 "references" 的解决方案 tsconfig.json;tsconfig.app.json(你的 src/、DOM lib、打包器解析、noEmit);tsconfig.node.json(vite.config.ts、node lib)。package.json 中会设置 "build": "tsc -b && vite build",你还需要添加独立的 "typecheck": "tsc -b --noEmit"。此处的 tsc -b 步骤仅执行类型检查,因为叶子配置设置了 noEmit。布局和完整文件见 references/vite-split-config.md。
第 4 步:为 monorepo 配置项目引用
对于应用会使用某个库或生成的包(例如生成的 API 客户端)的多包仓库:在被引用的包上设置 "composite": true(这会强制启用 declaration: true,并要求 include/files 匹配每个源文件),在使用方添加 "references": [{ "path": "../<pkg>" }] 条目,并使用 tsc -b 进行构建/检查。导入被引用项目时,会根据其生成的 .d.ts 解析;tsc -b 会按顺序构建依赖项,并通过 .tsbuildinfo 实现增量构建。两个包的示例见 references/project-references.md。通过 turborepo 技能,将生成的 typecheck 任务接入 monorepo 任务运行器(缓存、依赖顺序);此处无需重新推导任务流水线。
第 5 步:添加 CI 门禁
添加一个 CI 任务,在每次推送/PR 时运行 typecheck 脚本,以便类型错误导致构建失败(打包器不会检查类型)。GitHub Actions 的高层配置示例(检出 → pnpm 和带缓存的 Node → 安装 → pnpm run typecheck 或 turbo run typecheck)见 references/ci-gate.md;流水线/缓存的具体配置应由任务运行器技能负责。
规则
硬性规则(绝不可违反):
- **
tsc检查与构建彼此独立。**绝不要声称或暗示vite build/ esbuild / SWC 会验证类型。typecheck必须是独立脚本,也是独立的 CI 步骤。 - **必须设置
strict: true;仅有strict还不够严格。**至少还要启用noUncheckedIndexedAccess,并优先采用最严格的基础配置。 - **不要认为脚手架默认就严格——务必核实。**新生成的
tsconfig.app.json可能不包含strict: true;打开文件并确认(或使用extends: "@tsconfig/strictest")。绝不要想当然。 - **使用项目引用时,通过
tsc -b检查,不要直接运行tsc。**在解决方案文件上直接运行tsc -p会忽略references图;tsc -b(构建模式)会遵循该图,并支持增量构建。 composite: true会强制启用declaration: true,并要求所有文件都列在include/files中——请审慎设置outDir/tsBuildInfoFile。
偏好(可覆盖):
- 优先使用
extends: "@tsconfig/strictest"作为严格性底线,然后根据项目覆盖 module/jsx 配置块。 - 对打包器应用,优先选择
module: "esnext"(或"preserve")并搭配moduleResolution: "bundler";对 Node 库则使用nodenext。 - 使用
vite-plugin-checker快速获得编辑器内和开发时反馈,但必须额外保留 CI 的tsc检查关卡,绝不能以此替代。 - 默认保留
skipLibCheck: true以提升速度,同时了解其权衡(见注意事项)。
注意事项
- **“
vite build通过了,所以类型没问题。”**错误——这是本技能要避免的最重要误区。打包器移除了类型;只有tsc --noEmit检查了类型。务必单独运行typecheck脚本。 - **脚手架不会自动采用严格配置。**当前 create-vite 的
react-tstsconfig.app.json包含打包器和 lint 标志,但必须确认其中确实设置了strict: true(不同模板版本之间可能有所变化);请添加该设置或使用extends: "@tsconfig/strictest"。 - **
moduleResolution: "bundler"有硬性搭配要求。**它要求module为esnext或preserve(不能是commonjs)。只有设置了noEmit(或emitDeclarationOnly)时,才允许使用allowImportingTsExtensions: true——这正适用于仅进行类型检查的配置,但如果同时生成 JS,就会报错。 - **
exactOptionalPropertyTypes可能带来意外。**启用后,{ a?: string }不再接受{ a: undefined }——若要允许这种情况,必须写成a?: string | undefined。因此它不属于strict;请审慎添加,并预期需要修改可选属性的调用位置。 - **在引用配置中忘记使用
tsc -b。**对于仅包含references的解决方案tsconfig.json,运行tsc --noEmit并不能进行有用的检查——只有构建模式(tsc -b)才会遍历该图。typecheck脚本必须使用-b。 - **
skipLibCheck: true会隐藏真实错误。**它会跳过对所有.d.ts文件的类型检查(包括生成的客户端所输出的声明,以及相互冲突的node_modules库类型)。这是为了在速度与噪声之间做出的权衡;如果生成的.d.ts本身格式有误,这个设置会让错误漏过。 - **
verbatimModuleSyntax需要显式使用import type。**启用后,在值位置导入的类型不再会被移除,可能导致运行时崩溃——请用import type标记仅用于类型的导入。它取代了已弃用的importsNotUsedAsValues/preserveValueImports。
反模式
- “我们有代码检查工具,所以不需要
tsc。” 代码检查工具(Biome/ESLint)没有类型系统,无法发现类型错误。类型检查关卡不可或缺,且与代码检查相互独立。 - “切换到 SWC 插件后,就不需要
tsc这一步了。” 并非如此——SWC 是速度更快的转译器,仍然不会进行类型检查。构建插件的选择与类型检查关卡相互独立。 - “只要启用
skipLibCheck,错误就会消失。” 它会抑制声明文件错误,而不是你代码中的错误,还可能掩盖有问题的生成.d.ts。不要用它来压制真实的类型错误。 - “设置
strict: true,然后就说配置是严格的。” 这只是严格模式的底线;还应启用额外标志(至少包括noUncheckedIndexedAccess),或使用最严格的基础配置。 - “让 CI 依靠
vite build来发现类型问题。” 它永远做不到。CI 关卡必须将tsc/tsc -b --noEmit作为独立步骤执行(直接执行或通过任务运行器执行)。
输出
为项目建立可用的 TypeScript 类型检查关卡:一套真正严格的 tsconfig 配置(适用时包括 solution 配置和叶子配置)、一个独立于构建流程的 typecheck npm 脚本(tsc --noEmit 或 tsc -b --noEmit)、为任何已使用或生成的包配置好项目引用,以及一个运行检查并在类型错误时失败的 CI 步骤。使用者是下一个工作流阶段——此时,开发者或受调度的 Agent 已拥有打包器未提供的类型错误关卡,以及会强制执行该检查的 CI。
相关内容
biome(或任何代码检查技能)——代码检查/格式化的补充工具;它不会进行类型检查,这正是此技能存在的原因。vite——负责构建/打包;此技能只负责构建流程跳过的tsc检查。turborepo——负责单体仓库任务流水线/缓存;此技能提供它执行的typecheck任务。- Python 类比(仅为概念类比,工具链不同):独立的 Python 类型检查器,例如
ty,在 Python 中发挥的作用与tsc --noEmit在这里的作用相同,都是提供“独立的类型检查关卡”。
渐进式披露
references/strict-tsconfig.md— 完整的strict系列、推荐的额外标志及其具体行为、打包器模块配置块、可共享的基础配置,以及一个完整的严格tsconfig.app.json示例。编写或收紧 tsconfig 时加载。references/vite-split-config.md— Vite 的三文件 TS 布局、tsc -b && vite build+typecheck脚本,以及vite-plugin-checker。设置 Vite 应用的类型检查时加载。references/project-references.md—composite/引用/tsc -b/增量语义,附带一个完整的双包示例(app → generated-client),以及skipLibCheck。配置单体仓库时加载。references/ci-gate.md—tscCLI 标志参考、GitHub Actions 关卡结构,以及经过验证的tsgo/typescript-go 状态说明。添加 CI 或有人询问原生编译器时加载。references/sources.md— 研究来源。
正文预算
description≤ 1,024 个字符。- 正文 ≤ 约 500 行 / 5,000 个令牌;较长的内容放在
references/中,按需加载。