Effect Schema 的 BigDecimal 比较校验:isGreaterThanBigDecimal 等五个高阶校验器详解
发布时间:2026/9/13 21:08:04
分类:文化教育
浏览:1234

Effect Schema 的 BigDecimal 比较校验isGreaterThanBigDecimal 等五个高阶校验器详解【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code本文基于effect包 4.0.0 的 Schema 模块围绕其新增的BigDecimal比较校验 APIisGreaterThanBigDecimal、isGreaterThanOrEqualToBigDecimal、isLessThanBigDecimal、isLessThanOrEqualToBigDecimal、isBetweenBigDecimal展开。文章覆盖这五个校验器的语义、参数与边界行为并结合源码解析其基于Order与makeFilter的底层实现、对fast-check任意值生成的约束推导以及相应的测试用例帮助读者在需要精确小数范围约束的场景金额、利率、计量等中正确使用 Effect Schema 完成运行时校验。为什么需要 BigDecimal 校验器JavaScript 的Number基于 IEEE 754 双精度浮点数无法精确表示所有十进制小数而金融、计量、科学计算等领域要求数值比较不丢失精度。Effect 为此提供了任意精度十进制类型BigDecimal以value: bigint与scale: number表示见 BigDecimal.ts 的make构造函数但仅有数据类型还不够——Schema 还需要表达金额必须大于 0利率必须介于 0 到 1 之间这类约束。为此Schema 模块在 4.0.0 中新增了一组针对BigDecimal的比较校验器能够在解码decode阶段校验BigDecimal值是否满足大于、大于等于、小于、小于等于、区间等约束生成精确的期望expected错误消息如Expected a value greater than 1为fast-check属性测试推导符合约束的随机BigDecimal生成策略。五个校验器 API 总览以下五个校验器均定义在 Schema.ts属于validation类别自 4.0.0 起可用全部以BigDecimal.Order作为比较依据校验器语义参数边界isGreaterThanBigDecimal(exclusiveMinimum)大于指定值严格单个BigDecimal不含下界isGreaterThanOrEqualToBigDecimal(minimum)大于等于指定值单个BigDecimal含下界isLessThanBigDecimal(exclusiveMaximum)小于指定值严格单个BigDecimal不含上界isLessThanOrEqualToBigDecimal(maximum)小于等于指定值单个BigDecimal含上界isBetweenBigDecimal({ minimum, maximum, exclusiveMinimum?, exclusiveMaximum? })位于区间内配置对象默认两端包含可分别排除它们的用法完全一致作为Schema.BigDecimal.check(...)的参数使用例如import { BigDecimal, Schema } from effect // 校验金额严格大于 0 const PositiveAmount Schema.BigDecimal.check( Schema.isGreaterThanBigDecimal(BigDecimal.fromStringUnsafe(0)) ) // 校验利率在 [0, 1] 区间 const Rate Schema.BigDecimal.check( Schema.isBetweenBigDecimal({ minimum: BigDecimal.fromStringUnsafe(0), maximum: BigDecimal.fromStringUnsafe(1) }) )关于参数值的构造方式BigDecimal.fromStringUnsafe(123.45)从十进制字符串构造语义直观是推荐写法BigDecimal.make(123456n, 3)直接指定有效数字value与小数位scale即 123.456见 BigDecimal.ts。用 check 组合出带约束的 SchemaSchema.BigDecimal本身仅校验值是否为BigDecimal不附带范围约束比较校验器则通过Schema.bigDecimal.check(check)挂载过滤条件。check可以串联多个条件import { BigDecimal, Schema } from effect // 金额必须大于 0 且小于 1,000,000 const Amount Schema.BigDecimal.check( Schema.isGreaterThanBigDecimal(BigDecimal.fromStringUnsafe(0)), Schema.isLessThanBigDecimal(BigDecimal.fromStringUnsafe(1000000)) )校验器的语义与参数边界含/不含在测试中有严格定义见 Schema.test.tsisGreaterThanBigDecimal(1)2通过1失败错误消息Expected a value greater than 1isGreaterThanOrEqualToBigDecimal(1)1通过0失败错误消息Expected a value greater than or equal to 1isLessThanBigDecimal(1)0通过1失败错误消息Expected a value less than 1isLessThanOrEqualToBigDecimal(1)1通过2失败错误消息Expected a value less than or equal to 1isBetweenBigDecimal({ minimum: 1, maximum: 5 })3通过0失败错误消息Expected a value between 1 and 5。这些错误消息中的数值均由BigDecimal.format格式化输出——当scale绝对值达到 16 及以上时自动切换为科学计数法见 BigDecimal.ts因此即使边界值极小或极大报错信息依然可读。isBetweenBigDecimal 的区间边界配置isBetweenBigDecimal接受配置对象默认最小/最大值都是包含inclusive的可通过exclusiveMinimum/exclusiveMaximum分别排除边界import { BigDecimal, Schema } from effect // (1, 5)严格开区间 const Open Schema.BigDecimal.check( Schema.isBetweenBigDecimal({ minimum: BigDecimal.fromStringUnsafe(1), maximum: BigDecimal.fromStringUnsafe(5), exclusiveMinimum: true, exclusiveMaximum: true }) ) // [1, 5)上界排除 const HalfOpen Schema.BigDecimal.check( Schema.isBetweenBigDecimal({ minimum: BigDecimal.fromStringUnsafe(1), maximum: BigDecimal.fromStringUnsafe(5), exclusiveMaximum: true }) )对应的底层实现在 Schema.tsconst gte options.exclusiveMinimum ? greaterThan : greaterThanOrEqualTo const lte options.exclusiveMaximum ? lessThan : lessThanOrEqualTo return makeFilterT( (input) gte(input, options.minimum) lte(input, options.maximum), { expected: a value between ${formatter(options.minimum)}${options.exclusiveMinimum ? (excluded) : } and ${ formatter(options.maximum) }${options.exclusiveMaximum ? (excluded) : } // ... } )即排除下界时改用严格大于排除上界时改用严格小于并同步在错误消息中追加(excluded)标注错误消息Expected a value between 1 (excluded) and 5能精确说明区间形态。底层实现Order、makeFilter 与可复用工厂五个校验器并非为BigDecimal单独手写逻辑而是对通用工厂函数的特化实例化。四个单边界工厂分别位于 Schema.tsmakeIsGreaterThan({ order, formatter })返回(exclusiveMinimum, annotations?) Filter内部用Order.isGreaterThan(order)比较makeIsGreaterThanOrEqualTo({ order, formatter })返回(minimum, annotations?) Filter内部用Order.isGreaterThanOrEqualTo(order)makeIsLessThan({ order, formatter })返回(exclusiveMaximum, annotations?) Filter内部用Order.isLessThan(order)makeIsLessThanOrEqualTo({ order, formatter })返回(maximum, annotations?) Filter内部用Order.isLessThanOrEqualTo(order)。所有工厂最终都通过makeFilterT(predicate, annotations)生成一个可挂载到 schema 上的 Filter其 annotations 会携带expected消息与arbitrary.constraint.ordered供测试数据生成使用并可接收调用方传入的额外annotations。BigDecimal五个校验器的具体定义Schema.ts统一传入export const isGreaterThanBigDecimal makeIsGreaterThan({ order: BigDecimal_.Order, formatter: (bd) BigDecimal_.format(bd) })这里有两个关键设计order: BigDecimal_.Order比较顺序直接复用 BigDecimal.ts 中定义的Order实例。它先比较符号再通过scale对齐后比较bigint有效数字确保不同scale表示的同一数值如 1.5 与 1.50比较结果一致。formatter: (bd) BigDecimal_.format(bd)将BigDecimal格式化为十进制字符串必要时切换科学计数法用于生成人类可读的expected错误消息例如Expected a value greater than 1中的1。正因这套工厂设计是泛化的isGreaterThan/isGreaterThanOrEqualTo/isLessThan/isLessThanOrEqualTo/isBetween同样被复用于Number、Date、BigInt等有序类型见 Schema.ts 附近的isBetween、Schema.ts 的isBetweenDate、Schema.ts 的isBetweenBigIntBigDecimal版本只是换了一套order与formatter。与 BigDecimal / BigDecimalFromString 的配合Schema 模块还提供两个相关的数据类型 schemaSchema.BigDecimal校验值本身即为BigDecimal实例通过BigDecimal.isBigDecimal判定见 Schema.ts编码时输出为字符串Schema.BigDecimalFromString将字符串解析为BigDecimal解码用BigDecimal.fromString编码用BigDecimal.format见 Schema.ts。在实际项目中数据往往以 JSON 字符串而非BigDecimal实例进入系统。常见组合是先解析再校验import { BigDecimal, Schema } from effect // 先解析字符串再校验区间 [1, 5] const ParsedBoundedAmount Schema.BigDecimalFromString.pipe( Schema.filter( Schema.isBetweenBigDecimal({ minimum: BigDecimal.fromStringUnsafe(1), maximum: BigDecimal.fromStringUnsafe(5) }) ) )这样一次decode即可完成字符串 → 任意精度小数 → 范围校验的完整链路同时BigDecimalFromString会在编码阶段把结果重新序列化为字符串保证 JSON 传输格式一致。任意值生成属性测试中的边界处理Schema的校验器还承担着为fast-check推导随机测试数据的职责toArbitrary。当Schema.BigDecimal.check(...)挂载了有序约束后任意值生成会利用arbitrary.constraint.ordered中的order、minimum、maximum、exclusiveMinimum、exclusiveMaximum信息见 Schema.ts而不是简单地生成任意BigDecimal。为支持这一过程源码中实现了一组小数刻度scale处理辅助函数Schema.ts默认最大刻度bigDecimalDefaultMaxScale 20bigDecimalMaxScale取默认刻度与最小/最大值刻度排除边界时再加 1中的最大值bigDecimalValueConstraintsAtScale把最小/最大值按刻度对齐为bigint约束若最小大于最大则返回undefinedbigDecimalScaleConstraints通过二分查找确定可生成的最小可行刻度区间若无法生成任何满足条件的值例如开区间内没有整数值抛出错误Unable to derive an arbitrary for the ordered BigDecimal constraints。这些辅助函数的存在使得任意值生成可以覆盖大量边界场景相关测试见 toArbitrary.test.ts带小数的区间1.01 到 1.02同时排除上下界的开区间负小数的开区间-1.02 到 -1.01最小等于最大但两端均包含的单点区间此时仍可生成唯一值上界刻度远高于默认刻度如 0 到 0.00000000000000000001不可能区间minimum maximum且两端均排除1.01, 1.01 开区间时toArbitrary抛出Unable to derive an arbitrary for the ordered BigDecimal constraints组合校验isGreaterThanBigDecimal(1.01)isLessThanBigDecimal(1.01)同样不可生成任意值并抛错通过Order.flip(BigDecimal.Order)构造非自然顺序时校验器依然能正确工作toArbitrary.test.ts。这说明即便不手写fast-check生成器只要正确组合BigDecimal与比较校验器属性测试也能在满足约束的空间内自动采样同时对不可能满足的约束给出明确错误。实战示例金额与比例字段的完整校验将上述能力组合起来可以得到一个完整的业务模型示例import { BigDecimal, Schema } from effect // 收款金额字符串输入解析后必须大于 0 const Amount Schema.BigDecimalFromString.pipe( Schema.filter(Schema.isGreaterThanBigDecimal(BigDecimal.fromStringUnsafe(0))) ) // 折扣比例解析后必须位于 (0, 1) const DiscountRate Schema.BigDecimalFromString.pipe( Schema.filter( Schema.isBetweenBigDecimal({ minimum: BigDecimal.fromStringUnsafe(0), maximum: BigDecimal.fromStringUnsafe(1), exclusiveMinimum: true, exclusiveMaximum: true }) ) ) // 订单模型金额与折扣比例经过解析 范围校验 const Order Schema.Struct({ id: Schema.String, amount: Amount, discountRate: DiscountRate }) // 校验失败时抛出包含精确错误消息的 ParseError Order.decode({ id: o-1, amount: -5, discountRate: 1.5 }) // ParseError: amount: Expected a value greater than 0 // discountRate: Expected a value between 0 (excluded) and 1 (excluded)要点小结五个校验器分别覆盖、、、、区间共五种比较语义区间版本支持分别排除上下界它们都基于BigDecimal.Order与BigDecimal.format因此比较精确、报错可读且支持任意刻度含科学计数法回退底层由makeIsGreaterThan等四个单边界工厂与makeIsBetween区间工厂特化而来同一套机制也服务Number、Date、BigInt等类型与Schema.BigDecimalFromString配合可完成字符串 → 任意精度小数 → 范围校验 → 字符串输出的完整编解码链路挂载到check上后fast-check任意值生成会自动遵循约束并能在约束不可能满足时明确抛错。如果想深入了解过滤条件Filter体系、Order比较器或BigDecimal的完整运算能力可以继续阅读Schema.ts 中makeFilter、makeIsBetween等工厂与BigDecimal五个校验器的完整定义BigDecimal.ts 中Order、format、make等基础构件Schema.test.ts 中五个校验器的解码行为测试toArbitrary.test.ts 中任意值生成的边界场景测试。【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考