joi
joi copied to clipboard
Allow custom value type for ValidationResult
Support plan
- is this issue currently blocking your project? (yes/no): no
- is this issue affecting a production system? (yes/no): no
Context
- node version: 15.3.0
- module version: 17.4.2
- environment (e.g. node, browser, native): node
- used with (e.g. hapi application, another framework, standalone, ...): Next.JS
- any other relevant information: pretty much just using it to validate incoming API data
What problem are you trying to solve?
I'm currently writing a project in Typescript and am using Joi to validate incoming API data. What I would like to be able to do is cast the data to the correct type when I use the validate
function. It just seems clunky to me to have to validate some data then cast it to the correct type afterwards.
For example:
type RequestData = {
message: string
}
const schema = Joi.object<RequestData, true>({
message: Joi.string(),
})
const handler = (req, res) => {
const { value } = schema.validate(req.body)
const realValue: RequestData = value
// ... use realValue
}
I think it would be much nicer to just be able to do the following:
const handler = (req, res) => {
const { value } = schema.validate<RequestData>(req.body)
// ... use value
}
Do you have a new or modified API suggestion to solve the problem?
The Typescript definitions for ValidationResult
and validate
could be changed to include a generic type for the output. (Maybe even ObjectSchema
could override validate
to automatically use TSchema
)
ValidationResult
could be changed to:
interface ValidationResult<TValue = any> {
error?: ValidationError;
warning?: ValidationError;
value: TValue;
}
Then AnySchema
could be changed to:
interface AnySchema extends SchemaInternals {
// ...
validate<TValue = any>(value: any, options?: ValidationOptions): ValidationResult<TValue>;
// ...
}
All the different Schema
interfaces could also be modified to return the correct type, however that might introduce increased burden in terms of maintaining.
Additionally, a separate interface could be created that only includes the validate
function, and uses a generic type as the TValue
type. From there, all the separate Schema
interfaces could extend it, using the correct type, but again, that might come at the cost of increased burden.
All of this is a relatively simple change, and I would have gone straight to a pull request, but I wanted to make sure this is something that actually should be added.
This used to be the case for the types defined at @types/joi
. I've been using a helper function to achieve this.
I wonder if the generic on ValidationResult
was removed by any specific reason.
This is a conversion function that will retain the types of the other properties in the validation result even if the type definition changes:
import { ValidationResult } from 'joi';
function castValidationResult<T> (
result: ValidationResult
): {
[Property in keyof ValidationResult]: Property extends 'value'
? T
: ValidationResult[Property];
} {
return result;
}