alexjpotter / fluentvalidation-ts Goto Github PK
View Code? Open in Web Editor NEWA TypeScript-first library for building strongly-typed validation rules
License: Apache License 2.0
A TypeScript-first library for building strongly-typed validation rules
License: Apache License 2.0
Maybe I missed this in the docs somewhere but I can't seem to chain .mustAsync
and I'm unsure if I'm doing something wrong or if it is just not possible. The following example does not work. I'll keep digging in the docs and code but it'd be great if someone could help me understand why this does not work. Thanks ๐
import { AsyncValidator } from 'fluentvalidation-ts';
type MyType = {
field: string;
};
class Test extends AsyncValidator<MyType> {
constructor() {
super();
this.ruleFor('field')
.mustAsync(async () => true)
.mustAsync(async () => true);
}
}
Hi, really like the library. I was looking at class-validator and immediately hit the problem of not being able to validate properties together or set a validator for a nested object. I also have my roots in C# so I found your library via fluentvalidation.
The only problem I am having right now is that it is not very convenient to check if the result is actually failed validation or a successful one. Is this intentional?
I would expect to be able to call .isValid() on the result of the validation. How would you recommend checking for success?
Checking if there are no keys on the result via Object.keys(result).length === 0?
Need ability to get back all errors on validation, instead of stopping when a rule fails.
Currently have an object with an array of objects, and I want to continue to run subsequent roles even if a previous rules fails validation.
When you want to have a rule like 'Check that a string is neither null nor empty' you have to use notNull()
in combination with notEmpty
explicitly, so do:
this.ruleFor('name').notNull().notEmpty();
because
this.ruleFor('name').notEmpty();
would let name = null
to be valid.
Hi Alex,
First of all, thanks for your library and the work you have invested in it. I usually use Fluent Validation in .net so it was a great surprise to find your library and use it in typescript.
I need to import the ValueValidationResult type for certain cascading validations inside nested components.
Before (v2.3.0) you could import from node_modules/fluentvalidation-ts/dist, but now (v3.1.0) in dist there is only index.d.ts
Could you consider exporting Value ValidationResult in dist/index.d.ts in future versions?
export { AsyncValidator, ValidationErrors, SyncValidator as Validator, ValueValidationResult };
TIA! Regards
In FluentValidation it is possible to string together multiple when statements for a single property. In this library the behaviour does not work as expected. For example:
this.ruleFor("days")
.notEmpty()
.must([beNumeric, beAnInteger, beGreaterThanOrEqualTo(0)])
.withMessage("days must be greater than or equal to 0")
.must([beNumeric, beAnInteger, beLessThan(2000000000)])
.withMessage("The maximum allowed number size is 1,999,999,999")
.must((value, model) => asNumber(value) > 0 || asNumber(model.otherDays) > 0)
.withMessage("days and otherDays cannot both be 0")
.when((model) => model.dayCode== "weekday")
.null()
.withMessage("days must not be entered for weekendDays")
.when((model) => model.dayCode!= "weekendDay");
Is not the same as:
this.ruleFor("days")
.notEmpty()
.must([beNumeric, beAnInteger, beGreaterThanOrEqualTo(0)])
.withMessage("days must be greater than or equal to 0")
.must([beNumeric, beAnInteger, beLessThan(2000000000)])
.withMessage("The maximum allowed number size is 1,999,999,999")
.must((value, model) => asNumber(value) > 0 || asNumber(model.otherDays) > 0)
.withMessage("days and otherDays cannot both be 0")
.when((model) => model.dayCode== "weekday");
this.ruleFor("days")
.null()
.withMessage("days must not be entered for weekendDays")
.when((model) => model.dayCode!= "weekendDay");
The second set of code provides the expected behaviour.
Where is it.
If I want to create a new validator called beInteger
, I want to combine a few rules:
Is there a way to combine the first two custom rules with the built-in scalePrecision
validator and pass it to must
?
How Can I do the Date Validations? I didn't find any references
Uncaught (in promise) TypeError: e2 is null
_validate CoreValidator.ts:138
validate CoreValidator.ts:482
runValidateHandler Formik.tsx:199
runValidateHandler Formik.tsx:198
runAllValidations Formik.tsx:314
validateFormWithHighPriority Formik.tsx:336
useEventCallback Formik.tsx:1213
useFormik Formik.tsx:352
The only way I have found to stop this is to remove all the validation rules.
What's going on?
Issue: Can't find a way of validating objects in a ReadonlyArray property of an object.
Using this.ForEach('packages') yields the following error: "Argument of type '"packages"' is not assignable to parameter of type 'never'"
Ideal solution: this.ruleForEach('packages').must(value => value.weight.grams < 1000);
Hello;
I'm using webpack + typescript to compile my app, but I'm getting an error when building for production. Everything works in development mode. There error I'm getting is Uncaught TypeError: Class extends value undefined is not a constructor or null
. Do you have any idea what's going on, or have you seen that before?
Any plans for supporting async validations in the future?
Would be super great if the must
validation would allow for returning a promise from the custom function (or a new, mustAsync
was introduced), so that we could use requests to server to, for example, validate that the username is not already taken.
this.ruleFor("userName")
.must(async (userName) => {
// todo add request to api
return false;
})
.withMessage("username already taken");
Hi, thanks for your validation library!
This very nice, but I have some trouble when need validate some value with IF rule.
Exemple: IF value not empty validate it
Up to version 2.3.0 I was able to use the type ValidationErrors
as the mechanism I've created to validate my Vue components needs to track them. I was able to use:
import type { ValidationErrors } from 'fluentvalidation-ts/dist/ValidationErrors';
From version 3.0.2 I can no longer access that type:
import type { ValidationErrors } from 'fluentvalidation-ts';
Module '"fluentvalidation-ts"' declares 'ValidationErrors' locally, but it is not exported. ts(2459)
Would it be possible to expose that type?
TY
I have an object
{
a: number,
b: number
}
How do I write a validaton rule to require a + b <= 100
?
Hello,
First of all, thanks for the library! It's awesome as I have been using fluent validator for C# for a long time, and was missing this in typescript. Great work.
My issue - If there are no validation errors, methods .validate
and .validateAsync
returns an empty object {}
.
Then to check if there are errors I have to each time check if return value is an empty object.
Example (using lodash):
const validationError = await Validators.CreateOrderRequestValidator(req).validateAsync(req.body);
_.isEmpty(validationError) ? res.status(200).json(await addOrder(req.body)) : res.status(400).json(validationError);
Example (without lodash):
const validationError = await Validators.CreateOrderRequestValidator(req).validateAsync(req.body);
Object.keys(validationError).length > 0 ? res.status(200).json(await addOrder(req.body)) : res.status(400).json(validationError);
For me it's a bit inconvenient, would prefer if these methods would either return ValidationError or null instead {} ?
So I could replace above code with:
const validationError = await Validators.CreateOrderRequestValidator(req).validateAsync(req.body);
validationError ? res.status(400).json(validationError) : res.status(200).json(await addOrder(req.body));
Perhaps as a workaround I could try wrapping these methods in my own custom one, and check this empty object once..
Thanks!
Hello;
I am using your library to validate that a date fits between a min and max date. We are actually using a string to back the date because we don't care about time or timezones, just the literal date. Here's our "fake" date class:
type Digit = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0;
type NonZeroDigit = Exclude<Digit, 0>;
type ISODateYear = `20${Digit}${Digit}`;
type ISODateMonth = `0${NonZeroDigit}` | `1${0 | 1 | 2}`;
type ISODateDay = `0${NonZeroDigit}` | `${1 | 2}${Digit}` | `3${0 | 1}`;
// type ISODate = "2000-01-01" | "2000-01-02" | "2000-01-03" | "2000-01-04" | "2000-01-05" | "2000-01-06" | "2000-01-07" | "2000-01-08" | "2000-01-09" | "2000-01-10" | "2000-01-11" | "2000-01-12" | ... 37187 more ... | "2099-12-31"
export type ISODate = `${ISODateYear}-${ISODateMonth}-${ISODateDay}`;
If I have a rule on a property with such a type, we are getting an error:
// Expression produces a union type that is too complex to represent.
this.ruleFor("myDate").notNull().notEmpty().must(fitIntoSqlDateTime);
How is your library composing types such that I would get this error? What can I do to work around it?
I have used https://fluentvalidation.net/, which the docs for this library reference as an influence for this library, and indeed they do look very similar. In the C# version, I can write RuleFor(x => x).Must(...);
, and I'm wondering if there is any way to do the same here? Something akin to the following
import { Validator } from 'fluentvalidation-ts';
type FormModel = {
name: string;
age: number;
};
export default class MyValidator extends Validator<FormModel>
{
constructor() {
super();
this.ruleFor(x => x) // This isn't allowed. I don't want to specify a property here.
.must(x => x.name === "test" && x.age === 5);
}
}
I realize I could do something like
this.ruleFor("name").must((_, x) => x.name === "test" && x.age === 5);
but that feels like a hack. I also realize that it would be more proper to break this into 2 validation rules, 1 for name
and another for age
. This was just a quick example to illustrate the goal.
Thanks in advance!
Are there any plans to support error codes as part of the validation result?
I imagine something like this:
this.ruleFor('name')
.notEmpty()
.withMessage('Please enter your name')
.withCode('invalidName');
The problem is that the ValueValidationResult would have to be changed to contain objects instead of simple strings:
{
name: {
message: 'Please enter your name'
code: 'invalidName'
}
}
which would probably be a breaking change.
This feature is very useful in the FluentValidation C# library as it allows categorisation of applied rules, for e.g., into errors or warnings. Of course the ValidationError results would become more complex so as to provide a message and possible additional data.
Your library looks awesome, except one little part.
When I change a name of a property I want the Typescript compiler to throw me a warning about where that property was in the project, so I can go and change them.
So, it's more of a suggestion than an issue, to actually have it like this:
RuleFor(x => x.name)
You have already the structure of a type generic so that means that you have thought of that. Anyways, something to think of!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.