如何在静态 yup 模式中使用动态变量?
How to use a dynamic variable in a static yup schema?
我想静态创建一个 yup 模式(模式定义一次),每次调用它时都采用一个动态变量(每次调用的变量可以不同)。这可能吗?
例如,
// file: schema.js
// create the schema once
yup = require('yup');
const schema = yup.mixed().test(
'my-test-name',
'cannot be an existing value',
value => !myArray.includes(value) // How to reference myArray here?
// As written, it results in "ReferenceError: myArray is not defined"
);
module.exports = schema;
// other file that imports the schema:
schema = require('./schema.js');
let myArray = ['blue', 'green'];
schema.validateSync('yellow'); // should pass validation, because 'yellow' not in myArray
myArray = ['orange', 'yellow'];
schema.validateSync('yellow'); // should fail validation, because 'yellow' is in myArray
(我意识到每次使用该范围内的变量动态创建一个模式是可能的。但是,我在一个代码库中工作,其中包含许多静态定义的 yup 模式,具有将模式映射到它们相应的函数字段。我希望有一种方法能够仅将动态变量用于需要它们的几个模式,而不必将每个静态模式修改为动态。)
尝试导出创建动态模式的函数。请看下面。
// file: schema.js
// create the schema once
yup = require('yup');
// export as a function
module.exports = myArray => {
return yup.mixed().test(
'my-test-name',
'cannot be an existing value',
value => !myArray.includes(value)
);
};
// other file that imports the schema:
schema = require('./schema.js');
let myArray = ['blue', 'green'];
let blueGreenSchema = schema(myArray);
blueGreenSchema.validateSync('yellow');
myArray = ['orange', 'yellow'];
let orangeYellowSchema = schema(myArray);
orangeYellowSchema.validateSync('yellow');
要使用动态变量,需要 3 个条件:
- 使用第二个
Options
参数与 context
键 validateSync()
- 使用函数表达式而不是箭头函数声明
.test()
函数(因为 yup 将函数绑定到 this
)
- 在测试函数中,用
this.options.context.variableName
引用动态变量
例如,
const yup = require('yup');
// statically declare the schema
const schema = yup.mixed().test(
'my-test-name',
'cannot be an existing value', // error message
function test(value) {
// NOTE: this must not be an arrow function, because yup binds it to it's "this"
// Note the use of this.options.context to reference the dynamic variable
return !this.options.context.myArray.includes(value)
}
);
// Note the use of passing a { context: ... } as the second "options" parameter to validateSync()
ret = schema.validateSync('yellow', { context: { myArray: ['blue', 'green'] } } );
console.assert(ret === 'yellow'); // passes validation
let errorMessage;
try {
schema.validateSync('blue', { context: { myArray: ['blue', 'green'] } } );
}
catch(error) {
errorMessage = error.message;
}
console.assert(errorMessage === 'cannot be an existing value');
我想静态创建一个 yup 模式(模式定义一次),每次调用它时都采用一个动态变量(每次调用的变量可以不同)。这可能吗?
例如,
// file: schema.js
// create the schema once
yup = require('yup');
const schema = yup.mixed().test(
'my-test-name',
'cannot be an existing value',
value => !myArray.includes(value) // How to reference myArray here?
// As written, it results in "ReferenceError: myArray is not defined"
);
module.exports = schema;
// other file that imports the schema:
schema = require('./schema.js');
let myArray = ['blue', 'green'];
schema.validateSync('yellow'); // should pass validation, because 'yellow' not in myArray
myArray = ['orange', 'yellow'];
schema.validateSync('yellow'); // should fail validation, because 'yellow' is in myArray
(我意识到每次使用该范围内的变量动态创建一个模式是可能的。但是,我在一个代码库中工作,其中包含许多静态定义的 yup 模式,具有将模式映射到它们相应的函数字段。我希望有一种方法能够仅将动态变量用于需要它们的几个模式,而不必将每个静态模式修改为动态。)
尝试导出创建动态模式的函数。请看下面。
// file: schema.js
// create the schema once
yup = require('yup');
// export as a function
module.exports = myArray => {
return yup.mixed().test(
'my-test-name',
'cannot be an existing value',
value => !myArray.includes(value)
);
};
// other file that imports the schema:
schema = require('./schema.js');
let myArray = ['blue', 'green'];
let blueGreenSchema = schema(myArray);
blueGreenSchema.validateSync('yellow');
myArray = ['orange', 'yellow'];
let orangeYellowSchema = schema(myArray);
orangeYellowSchema.validateSync('yellow');
要使用动态变量,需要 3 个条件:
- 使用第二个
Options
参数与context
键validateSync()
- 使用函数表达式而不是箭头函数声明
.test()
函数(因为 yup 将函数绑定到this
) - 在测试函数中,用
this.options.context.variableName
引用动态变量
例如,
const yup = require('yup');
// statically declare the schema
const schema = yup.mixed().test(
'my-test-name',
'cannot be an existing value', // error message
function test(value) {
// NOTE: this must not be an arrow function, because yup binds it to it's "this"
// Note the use of this.options.context to reference the dynamic variable
return !this.options.context.myArray.includes(value)
}
);
// Note the use of passing a { context: ... } as the second "options" parameter to validateSync()
ret = schema.validateSync('yellow', { context: { myArray: ['blue', 'green'] } } );
console.assert(ret === 'yellow'); // passes validation
let errorMessage;
try {
schema.validateSync('blue', { context: { myArray: ['blue', 'green'] } } );
}
catch(error) {
errorMessage = error.message;
}
console.assert(errorMessage === 'cannot be an existing value');