Is it possible to use an enum for the property names of a Joi schema?
For example, given the following string-constants.enum.js file:
export default {
INPUT_BUSINESS_NAME: 'business-name',
INPUT_ADDRESS_LINE_1: 'address-line-1'
// etc...
}
What I want to do is:
const stringConstants = require('path/to/string-constants.enum')
const Joi = require('#hapi/joi')
const businessDetailsSchema = {
[stringConstants.INPUT_BUSINESS_NAME]: Joi.string().required(),
[stringConstants.INPUT_ADDRESS_LINE_1]: Joi.string().required(),
// etc...
}
However, when a fieldset that includes 'business-name' or 'address-line-1' fields is validated it throws an error saying that the fields are't defined in the schema.
If I use this though:
const bname = 'business-name'
const add1 = 'address-line-1'
const businessDetailsSchema = {
[bname]: Joi.string().required(),
[add1]: Joi.string().required(),
// etc...
}
Then it works OK - so it seems to be an issue with reading the values from an imported enum.
Thanks
Fixed it - needed to use import instaed of require to bring the enums in.
Works now
Related
I want that every time I use yup.string(), it will add a specific default value for it
for example:
const schema = yup.object({
text: yup.string()// I want it to also do .default('some string') in the background,
});
or - another option - is there any way to set the default value after creating the scheme? something like setDefault('text', 'some string')
The closest solution I came across to solve your issue is extending your string with a custom method that implements your needs. To do that you need to use addMethod from yup:
import { addMethod, string } from 'yup';
addMethod(string, 'append', function append(appendStr) {
return this.transform((value) => `${value}${appendStr}`);
});
Now, you can use your custom method (append) and apply it to any string you want:
string().append('~~~~').cast('hi'); // 'hi~~~~'
If you want to add the custom method to all your schema types like date, number, etc..., you need to extend the abstract base class Schema:
import { addMethod, Schema } from 'yup';
addMethod(Schema, 'myCustomMethod', ...)
Extra
For Typescript
In your type definition file, you need to declare module yup with your custom method's arguments and return types:
// globals.d.ts
import { StringSchema } from "yup";
declare module 'yup' {
interface StringSchema<TType, TContext, TDefault, TFlags> {
append(appendStr: string): this;
}
}
Unknow behavior for transform method
While I was trying to extend the functionality of the date schema with a custom method that transform the date that user enters from DD-MM-YYY to YYYY-MM-DD, the custom method broke after I used it with other methods like min, max for example.
// `dayMonthYear` should transform "31-12-2022"
// to "2022-12-31" but for some reason it kept
// ignoring the `cast` date and tried to transform
// `1900` instead!
Yup.date().dayMonthYear().min(1900).max(2100).required().cast("31-12-2022") // error
To work around this issue, I appended my custom method at the end of my schema chain:
Yup.date().min(1900).max(2100).required().cast("31-12-2022").dayMonthYear() // works as expected
This issue is mentioned in this GH ticket which I recommend going through it as it's going more in-depth on how to add custom methods with Typescript.
References
addMethod
Extending built-in schema with new methods
Example of addMethod in Typescript (GH ticket)
I have this:
const jsonField = { [key]: value };
How can I validate that with Yup?
Keeping in mind that the shape of the object changes a lot.
Found it!
It appears that Yup has a mixed validator to use in this case.
Yup.mixed()
Let's say I have a ColorPalette class that looks like the following:
class ColorPalette {
static const Map<int, Color> gray = {
400: Color(0xFFDDDDDD),
500: Color(0xFFEEEEEE),
// ...
};
// Primary colors in separate variable
static const Color primaryBlue = Color(0xFF0000FF);
// ...
}
And if I were to assign a color value of the map to a variable that expects a const value:
class SomeOtherClass {
static const Map<String, Color> stateColor = {
// Error
'pressed': ColorPalette.gray[500],
}
}
Complains that "Const variables must be initialized with a constant value."
But this works fine:
...
'pressed': ColorPalette.primaryBlue,
...
Plus when assigning map, doing 500: const Color(...) or static const Map<int, Color> gray = const {...} didn't work either.
So I suspect that this is throwing error probably because compiler doesn't evaluate all entries in the map during compile time and therefore, the value being accessed with the given key can be only known during runtime?
Is there any workaround to assign value from a map to a variable that expects a const value?
There is no workaround.
An expression of the form e1[e2] cannot be a constant. The [] operator is a method (all user-definable operators are), and you cannot call a method at compile time except for a very small number of operations on known system types. Map lookup, even on constant maps, is not one of those exceptions.
The reason ColorPalette.primaryBlue works is that it directly references a const variable.
Let's say I have a ColorPalette class that looks like the following:
class ColorPalette {
static const Map<int, Color> gray = {
400: Color(0xFFDDDDDD),
500: Color(0xFFEEEEEE),
// ...
};
// Primary colors in separate variable
static const Color primaryBlue = Color(0xFF0000FF);
// ...
}
And if I were to assign a color value of the map to a variable that expects a const value:
class SomeOtherClass {
static const Map<String, Color> stateColor = {
// Error
'pressed': ColorPalette.gray[500],
}
}
Complains that "Const variables must be initialized with a constant value."
But this works fine:
...
'pressed': ColorPalette.primaryBlue,
...
Plus when assigning map, doing 500: const Color(...) or static const Map<int, Color> gray = const {...} didn't work either.
So I suspect that this is throwing error probably because compiler doesn't evaluate all entries in the map during compile time and therefore, the value being accessed with the given key can be only known during runtime?
Is there any workaround to assign value from a map to a variable that expects a const value?
There is no workaround.
An expression of the form e1[e2] cannot be a constant. The [] operator is a method (all user-definable operators are), and you cannot call a method at compile time except for a very small number of operations on known system types. Map lookup, even on constant maps, is not one of those exceptions.
The reason ColorPalette.primaryBlue works is that it directly references a const variable.
I have declared a JOI schema/bean and cannot use that definition when declaring another schema/bean?
I get a syntax error on "arg: joi.object.schema(TestBean).required()" but can declare an array using a schema like: "argArray: joi.array().items(TestBean).required()"
const TestBean = joi.object().required().keys({
member1: joi.array().items(joi.string().required()),
member2: joi.number().required()
}).unknown(); // allow additional attributes
const BeanMethodDocument = joi.object().required().keys({
arg: joi.object.schema(TestBean).required(),
argArray: joi.array().items(TestBean).required(),
option: joi.string().valid('Empty','Full','HalfFull','HalfEmpty')
});
I am expecting that I can use pre-defined declarations of schemas.
I just need the proper syntax.
You're missing the function call on joi.object.
const BeanMethodDocument = joi.object().required().keys({
arg: joi.object().schema(TestBean).required(),
// ------------^
argArray: joi.array().items(TestBean).required(),
option: joi.string().valid('Empty','Full','HalfFull','HalfEmpty')
});