mcpField
T
typescript-typecheck

typescript-typecheck

github.com/bm629测试与质量5101 次安装1 天前更新
代码仓库

关于 typescript-typecheck

typescript-typecheck 是帮助 TypeScript 项目配置独立类型检查门禁的技能,面向开发者及维护 CI 的团队。它用严格的 tsconfig、独立的 tsc 检查和项目引用补足仅转译代码的构建流程,并将检查接入 CI。

主要功能

  1. 01配置严格的 tsconfig
  2. 02建立独立 tsc 类型检查脚本
  3. 03设置 Vite 分离式配置
  4. 04为 monorepo 配置项目引用
  5. 05在 CI 中运行类型检查

适用场景

  1. 01为新 TypeScript 项目设置类型检查门禁
  2. 02检查 bundler 应用的模块解析配置
  3. 03让 CI 阻止类型错误通过
  4. 04检查 monorepo 跨包类型

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bm629/agent-skills --skill typescript-typecheck

安装后在 Claude Code 中输入/typescript-typecheck确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ci-gate.md
project-references.md
sources.md
strict-tsconfig.md
vite-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-ts tsconfig.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 — tsc CLI 标志参考、GitHub Actions 关卡结构,以及经过验证的 tsgo/typescript-go 状态说明。添加 CI 或有人询问原生编译器时加载。
  • references/sources.md — 研究来源。

正文预算

  • description ≤ 1,024 个字符。
  • 正文 ≤ 约 500 行 / 5,000 个令牌;较长的内容放在 references/ 中,按需加载。

评论

支持 Markdown