-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validation and error syntax #22
Comments
How about this: const isVerified = p`{
name: String ||| "Name must be a string" &
{ length: > 7 } ||| "Length must be greater than 7" ,
age: (Number & > 18) ||| "Age must be numeric and over 18"
} ||| "You are not verified"`.validate; Then with white space: const isVerified = p`{
name: String ||| "Name must be a string"
& { length: > 7 } ||| "Length must be greater than 7" ,
age: (Number & > 18) ||| "Age must be numeric and over 18"
} ||| "You are not verified"`.validate;
const {errs,valid} = isVerified({name: 5678, age: 20});
console.log(valid); // false
console.log(errs); // ["Name must be a string", "You are not verified"] Caveats are that because "|||" is a right associated infix operator the commas will need to be respected which makes more sense when you don't use whitespace to align the errors. This would de-sugar to: const isVerified = err(
obj(
["name", and(err(String, "Name must be a string"),
err(obj(['length', gt(7)]), "Length must be greater than 7"))],
["age", and(Number, err(gt(18), "You must be over 18"))]
),
"You are not verified"
).validator; These can also be passed in as error keys so that way you can use localization. const isVerified = p` {
name: String ||| "name_must_be_string",
age: Number & > 18 ||| "you_must_be_over_18"
} ||| "you_are_not_verified"`;
const {errs} = isVerified.validate({name: 5678, age: 20});
console.log(errs.map(t)); // ["Name must be a string", "You are not verified"] Not totally sold on quotes or hashes. Hashes make parsing easier as we can generate an invisible err operator. Syntax highlighting will differentiate the errors from the code and wrapping them in hashes make them stand out. |
hmm... maybe we need a way to give each error a name as well as a message? 🤔 |
The other feature yup users might want here would be the const checkCanDrive = p`{
name
} & (
{ age: <= 18, canDrive: false } ||
{ age: >= 18, canDrive: true }
)`;
checkCanDrive({ name: "Paul", age: 17, canDrive: true }); //false
checkCanDrive({ name: "Paul", age: 17, canDrive: false }); //true
checkCanDrive({ name: "Mary", age: 18, canDrive: true }); // true |
We would also need a way to pass dynamic data to the error message. 🤔 Perhaps function expressions? const isVerified = p`{
name: String ||| ${o => `${o.name} must be a string!`},
age: Number & > 18 ||| ${o => `${o.age} must be greater than 18`}
} ||| ${o => `${o} is not verified`}`;
const {errs,valid} = isVerified.validate({name: 5678, age: 20});
console.log(valid); // false
console.log(errs); // [`5678 must be a string`, `{name:5678,age:20} is not verified`] |
@dmechea @thomasdavis @hannanmumtaz @lukekhamilton got any input here? Could use opinions. I played around with |
Sorry bro, JS really isn't my strong point. I'm all golang'n these days. |
AlternativesUse const isVerified = p`{
name: String | "Name must be a string" &
{ length: > 7 } | "Length must be greater than 7" ,
age: (Number & > 18) | "Age must be numeric and over 18"
} | "You are not verified"` Use const isVerified = p`{
name: String # "Name must be a string" &
{ length: > 7 } # "Length must be greater than 7" ,
age: (Number & > 18) # "Age must be numeric and over 18"
} # "You are not verified"`.validate; Use const isVerified = p`{
name: String :: "Name must be a string" &
{ length: > 7 } :: "Length must be greater than 7" ,
age: (Number & > 18) :: "Age must be numeric and over 18"
} :: "You are not verified"`.validate; Use const isVerified = p`{
name: String ||| "Name must be a string" &
{ length: > 7 } ||| "Length must be greater than 7" ,
age: (Number & > 18) ||| "Age must be numeric and over 18"
} ||| "You are not verified"`.validate; Use const isVerified = p`{
name: String #Name must be a string# &
{ length: > 7 } #Length must be greater than 7# ,
age: (Number & > 18) #Age must be numeric and over 18#
} #You are not verified#`.validate; Error strings as prefixes const isVerified = p`"You are not verified" ||| {
name: "Name must be a string" ||| String &
"Length must be greater than 7" ||| { length: > 7 },
age: "Age must be numeric and over 18" ||| (Number & > 18)
}`.validate; Prefixes with hash operator const isVerified = p`"You are not verified" # {
name: "Name must be a string" # String &
"Length must be greater than 7" # { length: > 7 },
age: "Age must be numeric and over 18" # (Number & > 18)
}`.validate; |
Still appreciate your input as I am creating my own language. You would have some good new syntax ideas! |
To me, this seams a little cryptic.. However I normally find JS to be like that. Biggest thing I love about go is how easy it is to read and understand. Very little having to decode the code. |
Out of interest are there any object schema validation libraries out there
in go?
|
Hey! I'm interested in this as a form validator I think it has some potential there for making form validation a bit more consistent across some libraries. Syntax wise I think you're on to something there I would say it does feel quite natural having something at the end, what actual symbol it is I don't mind. ? # :: it's all the same. I would like to provide some context for the way I've currently seen form validation done within the tools I use so that y'all all know what the patterns kind of are in this space: Redux form example via: https://redux-form.com/6.6.3/examples/fieldlevelvalidation/ const required = value => value ? undefined : 'Required'
const maxLength = max => value =>
value && value.length > max ? `Must be ${max} characters or less` : undefined
const maxLength15 = maxLength(15)
const number = value => value && isNaN(Number(value)) ? 'Must be a number' : undefined
const minValue = min => value =>
value && value < min ? `Must be at least ${min}` : undefined
const minValue18 = minValue(18)
const email = value =>
value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) ?
'Invalid email address' : undefined
const tooOld = value =>
value && value > 65 ? 'You might be too old for this' : undefined
const aol = value =>
value && /.+@aol\.com/.test(value) ?
'Really? You still use AOL for your email?' : undefined 🤮 Formstate via: https://formstate.github.io/#/?id=quick-example username = new FieldState('').validators((val) => !val && 'username required'); |
Yep the other thing to note for reference is we should also support default error messages based on configured locale. const someStringOrFalsy = p`{
name: string &
{ length: > 7 },
age: (Number & > 18)
}`.validate({name:"foo", age:23});// "Property length must be greater then 7" |
What has been annoying me about most of the above alternatives is that they don't scan well without syntax highlighting. I think the double colon before a string works the best as it gets out of the way and our eyes are used to bookending a string. It is also reasonably easy to parse with a regex (aside from escaped quotes). const isVerified = p`{
name: string :: "Name must be a string" &
{ length: > 7 } :: "Length must be greater than 7",
age: (number & > 18) :: "Age must be numeric and over 18"
} :: "You are not verified"`.validate; You can also loose the whitespace if required. const isVerified = p`{
name: string ::"Name must be a string"
& { length: > 7 } ::"Length must be greater than 7",
age: (number & > 18) ::"Age must be numeric and over 18"
} ::"You are not verified"`.validate; Or go nuts with whitespace: const isVerified = p`{
name: string :: "Name must be a string"
& { length: > 7 } :: "Length must be greater than 7",
age: (number & > 18) :: "Age must be numeric and over 18"
} :: "You are not verified"`.validate; |
Happy to say with #104 we have some working validation and from tonight it will be available on the
|
Just bumping this thread to say that validation syntax has changed and we also have Formik compatability: https://github.com/ryardley/pdsl#validation-with-formik. A new version is available on the |
Not sure exactly how to do this but having a way to diagnose failure say through an errors array would mean that pdsl could be used to validate form data.
This way I think PDSL could be used for object validation in a way similar to yup but more concise and with more intuitive syntax.
The text was updated successfully, but these errors were encountered: