is-kit 百星节点:类型守卫库的取舍与进化
is-kit 的 GitHub 星数到了 100。数字本身说明不了太多但放在 50 星到 100 星这段区间里有些变化比数字更值得说。50 星时作者想证明的是这个库不只是一个玩具。它已经被用在一个服务超过十万用户的 TypeScript 生产应用里用来替代重复的运行时检查并把 HTTP 错误、字面量联合、数组、API 返回值、普通对象等判断收成可复用的类型守卫。当时最重要的结论不是代码变短了而是这些检查有了统一的形状小守卫可以组合应用自己的辅助函数可以夹在库和业务代码之间组合结果仍然能参与正常的 TypeScript 控制流。这部分设计没有变。变的是库本身以及它被使用的方式。一个反复出现的需求是属性精炼。手里已经有一个可信的类型守卫比如判断字符串是否合法但想表达的是“这个对象有一个属性而且该属性是字符串”。听起来简单实际要区分几种情况必需属性和可选属性不同数组下标和对象属性不同可选属性在已知有值时怎么收窄、仍然可选时又怎么收窄也不一样。is-kit 为此增加了三个属性精炼辅助函数思路是把已有的守卫抬到属性或数组元素这一层而不是在另一个自定义谓词里重写一遍。这符合库一贯的取向不做一个大而全的校验器做能反复用的小检查。更大的新增是判别联合的穷尽校验 API。运行时验证一个判别联合并不难难的是让 TypeScript 确认校验器本身覆盖了整个联合。新的构建器会在编译期检查缺失的分支、多余的分支、不兼容的分支守卫、不完整的判别元组。手写类型守卫最容易出的问题是漂移TypeScript 类型改了运行时守卫没改编译器通常不会提醒。这个 API 就是在把这类错误变得难以发生。除了新增功能库也变得更严格。近期版本修正了字面量键收窄、原生品牌检查、带覆写迭代器的数组守卫、精确校验、symbol 键的 struct schema、跨 realm 的 struct schema 等行为。发布包层面的测试也增加了现在会同时从 ESM 和 CommonJS 的 TypeScript 消费者角度检查已发布包的表现。这些改动在代码片段里不好展示但对一个小库来说很重要——奇怪的 JavaScript 和 TypeScript 环境才是真实世界的考验。作者自己的使用方式也在变。在 changelog 工具等其它开源项目里他开始自然地用 is-kit 保持小谓词可复用、可组合而不是把每个运行时检查都做成孤立辅助函数。他说现在不再想“这里应该用我的库”而是直接拿需要的守卫来用。一个库对维护者开始有用往往就是从它不再像自己的演示品开始的。最近一次有意思的反馈来自一个真实使用场景。有人把 is-kit 的守卫用在 Effect 的 filter 里精炼逻辑本身很普通但 Effect 的错误通道被意外拓宽成了 unknown。原因是精炼函数的输入类型参与泛型推断重新定义了 Effect 已经确定的错误类型。相关修复已经合并进 Effect思路是只让 Effect 的 Error 槽影响类型不让精炼的输入类型覆盖它同时为 Channel、Effect、Stream 补了类型测试。is-kit 没有“弄坏 Effect”那个精炼的输入类型本来就有意放宽问题出在两个泛型 API 相遇时的微妙推断。这种边缘情况很难靠单独测试发现。100 星仍然不算大项目。星数不是基准不是正确性证明也不意味着每个 TypeScript 项目都该安装它。但和 50 星时相比事情确实不一样了有人使用、提问、找边缘情况、报 bug、把它和其他校验方案比较、拿它的守卫配合别的库也有人让作者重新考虑本以为已经完成的 API。这些比数字更有价值。项目定位也变得更清楚。is-kit 不打算取代 schema 库不打算把所有运行时值都塞进 schema-first 流程也不打算隐藏正常的 TypeScript 控制流。它要回答的问题很小这个值能否安全地进入这个分支如果需要丰富的校验错误、数据变换、表单验证或跨系统共享的契约Zod、Valibot 之类的工具更合适。但如果已经有普通的 TypeScript 代码只缺一个可复用的收窄函数那就是 is-kit 想待的位置。小型的运行时判断普通的函数普通的 TypeScript。对想尝试的人来说实用的判断标准是你是否在重复写零散的运行时检查是否希望这些检查能组合并保留收窄是否不想为此引入完整的 schema 工作流。如果答案偏向肯定它值得一看如果主要需求是复杂校验和错误信息先看成熟的 schema 库。