You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript中为自定义类实现Chai风格的should.be.a.integer链式语法

实现思路

这类无括号链式属性调用的核心是利用JavaScript的访问器属性(Getter),每个中间链式节点(比如should、be、a这类语义衔接属性)返回携带当前实例上下文的对象,访问到最终断言属性(比如integer)时执行对应的校验逻辑即可。

基础版实现

class AnyClass {
  // 此处以校验实例的value属性为例,可替换为你需要校验的任意目标
  constructor(value) {
    this.value = value
  }

  // 链式入口属性
  get should() {
    const self = this // 保存当前实例上下文
    return {
      // 中间链式节点be
      get be() {
        return {
          // 中间链式节点a
          get a() {
            return {
              // 最终断言属性:校验是否为整数
              get integer() {
                if (!Number.isInteger(self.value)) {
                  throw new Error(`Expected ${self.value} to be an integer`)
                }
                // 返回当前节点可支持后续继续链式调用
                return this
              },
              // 可扩展其他断言属性
              get string() {
                if (typeof self.value !== 'string') {
                  throw new Error(`Expected ${self.value} to be a string`)
                }
                return this
              }
            }
          }
        }
      }
    }
  }
}

调用测试

// 合法值无报错
new AnyClass(100).should.be.a.integer

// 非法值抛出错误
try {
  new AnyClass('100').should.be.a.integer
} catch (e) {
  console.log(e.message) // 输出:Expected 100 to be an integer
}

通用扩展方案

如果需要大量语义衔接词(比如an、and、is这类无实际逻辑仅做语义优化的词),可以用工厂函数批量生成链式节点,避免重复写嵌套getter:

// 链式节点生成工厂
function createChainNode(context, assertions) {
  const node = {}
  // 批量注册语义衔接词,全部返回当前节点本身,支持任意顺序调用
  const semanticWords = ['be', 'a', 'an', 'is', 'and', 'that', 'has']
  semanticWords.forEach(word => {
    Object.defineProperty(node, word, {
      get: () => node
    })
  })
  // 注册所有断言属性
  Object.entries(assertions).forEach(([assertName, handler]) => {
    Object.defineProperty(node, assertName, {
      get: () => {
        handler.call(context)
        return node
      }
    })
  })
  return node
}

// 改造后的AnyClass
class AnyClass {
  constructor(value) {
    this.value = value
  }

  get should() {
    return createChainNode(this, {
      integer: function() {
        if (!Number.isInteger(this.value)) throw new Error(`Expected ${this.value} to be integer`)
      },
      positive: function() {
        if (this.value <= 0) throw new Error(`Expected ${this.value} to be positive`)
      },
      string: function() {
        if (typeof this.value !== 'string') throw new Error(`Expected ${this.value} to be string`)
      }
    })
  }
}

// 支持灵活的链式写法,语义词顺序不影响效果
new AnyClass(200).should.be.a.positive.integer
new AnyClass('hello').should.is.a.string

内容的提问来源于stack exchange,提问作者Ebraheem Ijaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 05:00:04