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

Joi自定义验证扩展未生效问题排查求助

问题分析与解决方案

你的问题核心是混淆了Joi的自定义类型扩展和规则扩展的写法:

  1. 你通过type: 'address'定义了一个全新的自定义类型,但验证逻辑却放在了rules字段下的address规则中——这个规则是用于给现有类型(比如string)添加额外验证的,而非自定义类型本身的验证逻辑。
  2. 当你调用joiExtended.address()时,Joi只会使用该类型的base(即string类型)进行基础验证,不会触发rules里的验证逻辑,所以你的console.log和错误永远不会执行。

修正后的代码

将验证逻辑从rules移到扩展对象的顶层validate属性中,这才是自定义类型的验证入口:

const Joi = require('joi')

const joiExtended = Joi.extend({
  type: 'address',
  base: Joi.string(),
  messages: {
    'address.invalid': 'invalid',
  },
  // 自定义类型的验证逻辑直接放在顶层validate中
  validate(value, helpers) {
    console.log('Validating address', value)
    // 测试用:所有输入都失败
    return { value, errors: helpers.error('address.invalid') }
  }
})

try {
  console.log(joiExtended.attempt('x', joiExtended.address()))
} catch (err) {
  console.error(err.message)
}
console.log(joiExtended.attempt('foo', joiExtended.number()))

执行结果

运行修正后的代码后,会得到预期结果:

  • 控制台打印Validating address x
  • 抛出ValidationError: invalid
  • 数字校验的sanity check依然正常抛出Error [ValidationError]: "value" must be a number

额外说明

如果你原本想给string类型添加一个address验证规则(而非自定义类型),写法应该是这样:

const joiExtended = Joi.extend({
  type: 'string',
  base: Joi.string(),
  messages: {
    'string.address': 'invalid address',
  },
  rules: {
    address: {
      validate: (value, helpers) => {
        console.log('Validating address rule', value)
        return { value, errors: helpers.error('string.address') }
      }
    }
  }
})

// 使用时需要链式调用.address()规则
joiExtended.attempt('x', joiExtended.string().address())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:13:27