news 2026/10/22 19:40:34

fast-check 3.16.0 新特性解析:fc.pre 类型收窄、ESM 迁移与文档站点性能优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fast-check 3.16.0 新特性解析:fc.pre 类型收窄、ESM 迁移与文档站点性能优化
  • 开发工具
  • 测试

【免费下载链接】fast-check

Property based testing framework for JavaScript (like QuickCheck) written in TypeScript

项目地址:https://gitcode.com/gh_mirrors/fa/fast-check
点击查看免费下载

本文基于 fast-check 官方发布博客(website/blog/2024-03-04-whats-new-in-fast-check-3-16-0/index.md)展开,结合当前仓库源码逐项验证 3.16.0 的三个核心变化:fc.pre正式成为 TypeScript 断言函数(assertion function)、monorepo 全面向 ECMAScript Modules 迁移、以及官网性能接近 PageSpeed 满分。读完本文,你将理解fc.pre的类型收窄原理与底层执行机制,掌握 ESM 双格式发布的现状,并了解一套可复用的静态文档站点性能优化清单。

一、fc.pre成为断言函数:让类型在测试中自动收窄

1.1 版本发布前的问题:pre 之后仍需手动断言

fc.pre是 fast-check 中声明前置条件(precondition)的核心 API,用于在属性测试中丢弃不符合前提的生成值。在 3.16.0 之前,fc.pre的返回类型无法向 TypeScript 表达"调用成功后条件必然成立"这一信息,因此开发者不得不额外写出类型断言:

// entries: {value: T} const match = entries.find((e) => e.value === needle); fc.pre(match !== undefined); // ❌ Previous (<3.16.0): match: {value: T} | undefined // ✅ Now (≥3.16.0): match: {value: T}

升级到 3.16.0 之后,fc.pre(match !== undefined)一行即可让编译器在后续代码中将match收窄为{value: T},不再需要手写as或!。

1.2 源码级验证:asserts签名与失败语义

在 packages/fast-check/src/check/precondition/Pre.ts 中,pre的实现只有几行:

export function pre(expectTruthy: boolean): asserts expectTruthy { if (!expectTruthy) { throw new PreconditionFailure(); } }

关键点有两个:

  • asserts expectTruthy签名:这是 TypeScript 3.7 引入的断言函数语法,它向编译器声明"若此函数正常返回,则传入的表达式必然为真",从而触发后续代码的类型收窄(narrowing)。
  • 失败即抛异常:当条件为假时抛出PreconditionFailure。该异常类定义在 packages/fast-check/src/check/precondition/PreconditionFailure.ts,内部通过Symbol.for('fast-check/PreconditionFailure')作为全局共享足迹(footprint),isFailure(err)静态方法据此识别"由 fast-check 抛出的前置条件失败",即使跨包实例(如fc.pre(false)与其他实例互认)也能正确判定。

1.3 底层执行机制:前置条件失败为何不算测试失败

PreconditionFailure被抛出后,由属性执行层捕获并特殊处理。在 packages/fast-check/src/check/property/_internals/PropertyImplem.ts 中:

function errorToPropertyAnswer(err: unknown) { // precondition failure considered as success for the first version if (PreconditionFailure.isFailure(err)) return err; // exception as PropertyFailure in case of real failure return { error: err }; }

也就是说,fc.pre抛出的是"本轮生成值被丢弃"的信号,会被转换为PreconditionFailure返回值,而不是PropertyFailure——这正是属性测试中"such that precondition holds"语义的落地。运行器在 RunnerIterator.ts 中同样只把非PreconditionFailure的结果当作真实失败处理。

对应的单元测试位于 packages/fast-check/src/check/precondition/Pre.spec.ts,覆盖了三个行为:真值不抛异常、假值抛出可识别的PreconditionFailure、以及跨 fast-check 实例的异常互认。

1.4 实战用法与取舍

在 website/docs/core-blocks/properties.md 中,官方文档将属性测试公式拆解为:"for any (x, y, ...)" 由 arbitraries 负责,"such that precondition(x, y, ...) holds" 由fc.pre或.filter负责,"predicate(x, y, ...) is true" 由断言负责。典型写法如下:

fc.property(fc.nat(), fc.string(), (maxLength, label) => { fc.pre(label.length <= maxLength); // 任何 label.length > maxLength 的生成值都会被丢弃 return crop(label, maxLength) === label; });

仓库示例中也大量使用该 API,例如 examples/003-misc/roman/main.spec.ts 中的fc.pre(n1 !== n2),以及 examples/002-recursive/isSearchTree/main.spec.ts 中对非排序遍历的前置过滤。

需要留意的是,官方文档同时强调:fc.pre与.filter本质上都是"先生成、后丢弃",过滤条件过严会显著浪费生成量。因此只要 arbitrary 本身支持约束(如fc.string({ minLength: 2 })),应优先使用生成器参数而非过滤手段。

二、迈向 ECMAScript Modules:monorepo 双格式发布路线

2.1 为什么迁移:ESM 是模块标准的正统继承者

ECMAScript Modules 是 CommonJS(Node.js)以及 Require/AMD/UMD(浏览器端)的官方继任者,目标是为不同运行时提供统一的import方式。fast-check 起步时 ESM 在 Node.js 中几乎不可用,直到 12.17.0 才出现第一个不带 flag 的版本;彼时生态尚未就绪,因此项目长期停留在 CommonJS。

2.2 迁移进度:先包后主,逐步推进

3.16.0 发布时,monorepo 的迁移策略是在各包package.json中逐个加入"type": "module",当时除/packages/fast-check(进行中)与/website(Docusaurus 暂不支持)外,其余包均已迁移完成。从当前仓库验证:

  • 根目录 package.json 与各子包均已声明"type": "module":
    • packages/ava/package.json
    • packages/jest/package.json
    • packages/vitest/package.json
    • packages/worker/package.json
    • packages/poisoning/package.json
    • packages/packaged/package.json
  • packages/fast-check/package.json 当前版本为 4.10.2,同样已是"type": "module",说明博客中标注为"进行中"的主包迁移后续已随 4.x 大版本完成,其exports字段指向./lib/fast-check.js。

2.3 对用户的影响:双版本仍会同时发布

博客明确承诺:迁移对用户"无可见影响",因为官方仍计划同时发布 ESM 与 CommonJS 两种产物。这意味着无论使用方的模块体系是 CJS 还是 ESM,都可以继续通过既有方式引入 fast-check;迁移更多是构建链(rolldown)与仓库内部工具链的现代化,而非破坏性的 API 变更。配套的 CI 改动(如 PR#4591 将 monorepo 根构建链迁移到 ESM、PR#4650 将 examples 构建链迁移到 ESM)也印证了"自下而上、逐层迁移"的推进方式。

三、更高效的文档:一套可复用的站点性能优化清单

3.1 背景:以 PageSpeed 为基准做性能评估

官方文档站(fast-check.dev)是用户了解 API 的关键资源。2024 年 2 月初,团队开始用 PageSpeed(Lighthouse 在线版)评估首页性能,先处理了一批"低垂果实",随后发现部分优化必须更换托管基础设施,于是迁移到能更精细控制响应头(cache-control、content-security-policy)的 Netlify。截至 3.16.0 发布,移动端评分已接近 100/100。

3.2 六项关键优化及其原理

  • 消除图片引起的布局偏移(layout shift):图片出现时若没有预留空间会导致页面跳动。做法是在 DOM 中直接为图片声明height与width,从根源上减少 CLS 指标。
  • 更合理的缓存策略:静态资源必须被缓存。此前 GitHub Pages 对静态资源仅缓存几分钟,缓存形同虚设;切换托管方案后缓存头得以正确配置。
  • 移除 Google Analytics:实测该脚本占据了约 50% 的 JavaScript bundle 体积与 50% 的主线程阻塞时间,属于性价比极低的性能负担,因而被移除(对应 PR#4776)。
  • 按真实比例提供图片:例如 16/9 的图片不应以 16/10 的尺寸渲染,避免拉伸与多余的解码开销。
  • 按实际展示尺寸提供图片:头像只需 64×64 就绝不下发更大文件,做到"既不更大也不更小"。
  • 优化 SVG 资源:SVG 可去除不影响观感的冗余细节(元数据、多余路径等),从而减小体积(对应 PR#4732 "Optimize SVG assets")。

3.3 安全与质量配套:CSP 与 CI 校验

性能之外,同批改动还包含安全加固与 CI 质量门禁:

  • Content-Security-Policy:为 fast-check.dev 配置并强制启用 CSP(PR#4753、PR#4761),随后为兼容 Algolia 搜索放宽策略(PR#4772)。
  • CI 校验:新增 Docusaurus 的onBrokenAnchors检查(PR#4598),让失效锚点直接导致构建失败;部署迁移到 Netlify(PR#4747)并移除 GitHub Pages 配置(PR#4751),同时让 CI 在无效部署时失败(PR#4756)。

这些实践对任何以文档站为核心的开发者项目都有直接参考价值:先量化(PageSpeed),再分级(低垂果实 → 基础设施),最后用 CI 门禁守住质量。

四、3.16.0 更新日志(自 3.15.0 起)

3.16.0 基于 3.15.1,但相比 3.15.0 的主要变更如下:

Features

  • 让fc.pre成为断言函数(PR#4709)——即本文第一节所述的类型收窄能力。

Fixes

  • Bug:小屏幕下 Logo 比例错误(PR#4736)。
  • CI:monorepo 根构建链迁移到 ESM(PR#4591);Docusaurus 增加onBrokenAnchors检查(PR#4598);补充 VSCode 配置文件(PR#4606);examples 构建链迁移到 ESM(PR#4650);官网部署迁移到 Netlify(PR#4747);移除 GitHub Pages 配置(PR#4751);CI 对无效部署报错(PR#4756);移除 Google Analytics(PR#4776)。
  • Clean:移除针对 React 17 的遗留补丁(PR#4769)。
  • Doc:在 website/docs/ecosystem.md 中新增idonttrustlikethat-fast-check与@effect/schema;在 track record 中新增jsonwebtoken;新增贡献者 nielk、ej-shafran、gruhn;修复官网控制台报错;优化首页图片与 SVG 资产、消除布局偏移;为 CTA 增加顶部留白;发布 3.15.0 博客(PR#4554、PR#4563、PR#4669、PR#4677、PR#4712、PR#4713、PR#4730、PR#4732、PR#4735、PR#4750、PR#4754、PR#4768、PR#4771)。
  • Security:为 fast-check.dev 配置并强制 CSP,随后为 Algolia 放宽策略(PR#4753、PR#4761、PR#4772)。
  • Test:修复 double 的isCorrect检查(PR#4665);稳定 URL 相关的不稳定测试(PR#4666)。

五、小结

fast-check 3.16.0 是一次"体验与基建并重"的版本:对使用者最直观的是fc.pre获得断言函数签名,让前置条件过滤的同时自动完成类型收窄,且其"抛出PreconditionFailure→ 被属性执行层识别为丢弃而非失败"的机制在 PropertyImplem.ts 中清晰可见;对维护者而言,ESM 迁移与文档站性能优化则为 4.x 大版本铺平了道路。从当前仓库看,这些计划均已落地:主包 package.json 已切换为"type": "module",各子包亦然,双格式发布策略得以延续。如需深入阅读,可继续查看 properties 文档 与 Pre 的单元测试。

  • 开发工具
  • 测试

【免费下载链接】fast-check

Property based testing framework for JavaScript (like QuickCheck) written in TypeScript

项目地址:https://gitcode.com/gh_mirrors/fa/fast-check
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 15:52:42

JavaScript汉字拆分:按Unicode字素簇安全切分中文文本

简介&#xff1a;这是一份面向前端开发者与汉字信息处理学习者的JavaScript汉字结构拆分工具代码&#xff0c;解决汉字部首与部件级解析需求&#xff0c;适用于汉字教学工具开发、输入法逻辑实现及搜索引擎关键词扩展等场景。资源为单文件Word文档&#xff08;.doc&#xff09;…

作者头像 李华
网站建设 2026/10/22 21:48:14

AI编程助手实战:从零搭建宠物生命周期管理App全流程

1. 为什么我选择用 AI 编程助手从零搭建这个宠物生命周期管理 App宠物生命周期管理这个需求&#xff0c;最早是我在一个养了三只猫的朋友身上看到的。他家老大从接回家到去年走完最后一程&#xff0c;整整十二年&#xff0c;疫苗记录散落在三四个不同的本子里&#xff0c;驱虫时…

作者头像 李华
网站建设 2026/10/22 14:28:30

C++加载TensorFlow PB模型实战:从环境配置到推理优化

1. 为什么要在C里加载PB模型把训练好的模型塞进C工程&#xff0c;是很多做算法落地的人绕不开的一步。Python那边调model.predict()两行代码搞定的事&#xff0c;到了C这边就变成了一堆API、指针和内存管理的组合拳。我最早接触这个需求是在一个工业质检的模拟项目里&#xff0…

作者头像 李华
网站建设 2026/10/22 19:39:34

51单片机贪食蛇游戏机开发实战:从硬件搭建到代码避坑

简介&#xff1a;一套基于89C52单片机的贪食蛇游戏机设计资料&#xff0c;配合清翔MCS51开发板使用&#xff0c;适合单片机入门与课程设计人群。整体包含代码工程与上位机软件&#xff0c;覆盖8x8点阵LED主屏、LCD1602状态显示、按键/红外遥控/上位机三种操作方式&#xff0c;以…

作者头像 李华
网站建设 2026/10/19 0:46:05

HTML页面国密SM4加密解密:纯JS实现与联调避坑指南

简介&#xff1a;一份面向网页前端开发者的国密加密解密演示资源&#xff0c;压缩包内共有两个文件&#xff0c;分别是一个网页页面和一个脚本文件&#xff0c;整体体积约五KB&#xff0c;非常轻量。页面完整展示了国密加密算法在密码块链接模式与电子密码本模式两种方式下的加…

作者头像 李华