Skip to content

Commit

Permalink
Merge pull request #2838 from hapijs/feat/validate-async-types
Browse files Browse the repository at this point in the history
feat: change validateAsync return type to match options
  • Loading branch information
Marsup committed Sep 21, 2022
2 parents 88d60ff + 7afdbec commit 96bbfdd
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 11 deletions.
32 changes: 25 additions & 7 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// The following definitions have been copied (almost) as-is from:
// https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/hapi__joi
//
//
// Note: This file is expected to change dramatically in the next major release and have been
// imported here to make migrating back to the "joi" module name simpler. It include known bugs
// and other issues. It does not include some new features included in version 17.2.0 or newer.
Expand Down Expand Up @@ -107,7 +107,7 @@ declare namespace Joi {
allowUnknown?: boolean;
/**
* when true, return artifacts alongside the value.
*
*
* @default false
*/
artifacts?: boolean;
Expand Down Expand Up @@ -196,6 +196,12 @@ declare namespace Joi {
}

interface AsyncValidationOptions extends ValidationOptions {
/**
* when true, artifacts are returned alongside the value (i.e. `{ value, artifacts }`)
*
* @default false
*/
artifacts?: boolean;
/**
* when true, warnings are returned alongside the value (i.e. `{ value, warning }`).
*
Expand Down Expand Up @@ -594,7 +600,7 @@ declare namespace Joi {
iterables?: boolean;

/**
* when true, the value of the reference is used instead of its name in error messages
* when true, the value of the reference is used instead of its name in error messages
* and template rendering. Defaults to false.
*/
render?: boolean;
Expand Down Expand Up @@ -734,7 +740,7 @@ declare namespace Joi {

type NullableType<T> = undefined | null | T

type ObjectPropertiesSchema<T = any> =
type ObjectPropertiesSchema<T = any> =
T extends NullableType<string>
? Joi.StringSchema
: T extends NullableType<number>
Expand All @@ -753,7 +759,7 @@ declare namespace Joi {

type PartialSchemaMap<TSchema = any> = {
[key in keyof TSchema]?: SchemaLike | SchemaLike[];
}
}

type StrictSchemaMap<TSchema = any> = {
[key in keyof TSchema]-?: ObjectPropertiesSchema<TSchema[key]>
Expand Down Expand Up @@ -910,7 +916,7 @@ declare namespace Joi {
* @param id - any value other than undefined which will be returned as-is in the result artifacts map.
*/
artifact(id: any): this;

/**
* By default, some Joi methods to function properly need to rely on the Joi instance they are attached to because
* they use `this` internally.
Expand Down Expand Up @@ -1210,7 +1216,19 @@ declare namespace Joi {
/**
* Validates a value using the schema and options.
*/
validateAsync(value: any, options?: AsyncValidationOptions): Promise<TSchema>;
validateAsync<TOpts extends AsyncValidationOptions>(
value: any,
options?: TOpts
): Promise<
TOpts extends { artifacts: true } | { warnings: true }
? { value: TSchema } & (TOpts extends { artifacts: true }
? { artifacts: Map<any, string[][]> }
: {}) &
(TOpts extends { warnings: true }
? { warning: ValidationError[] }
: {})
: TSchema
>;

/**
* Same as `rule({ warn: true })`.
Expand Down
20 changes: 16 additions & 4 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -984,18 +984,19 @@ schema = Joi.link(str);
{ // validate tests
{
let value = { username: 'example', password: 'example' };
const schema = Joi.object().keys({
type TResult = { username: string; password: string };
const schema = Joi.object<TResult>().keys({
username: Joi.string().max(255).required(),
password: Joi.string().pattern(/^[a-zA-Z0-9]{3,255}$/).required()
});
let result: Joi.ValidationResult;
let asyncResult: Promise<any>;

value = schema.validate(value).value;
let asyncResult: Promise<TResult>;

result = schema.validate(value);
if (result.error) {
throw Error('error should not be set');
} else {
expect.type<TResult>(result.value);
}
result = schema.validate(value, validOpts);
asyncResult = schema.validateAsync(value);
Expand All @@ -1006,6 +1007,17 @@ schema = Joi.link(str);
.then(val => { throw new Error('one error'); })
.catch(e => { });

expect.type<Promise<TResult>>(schema.validateAsync(value));
expect.type<Promise<{ value: TResult, artifacts: Map<any, string[][]> }>>(schema.validateAsync(value, { artifacts: true }));
expect.type<Promise<{ value: TResult, warning: Joi.ValidationError[] }>>(schema.validateAsync(value, { warnings: true }));
expect.type<Promise<{ value: TResult, artifacts: Map<any, string[][]>; warning: Joi.ValidationError[] }>>(schema.validateAsync(value, { artifacts: true, warnings: true }));
expect.error<Promise<{ value: TResult, warning: Joi.ValidationError[] }>>(schema.validateAsync(value, { artifacts: true }));
expect.error<Promise<{ value: TResult, artifacts: Map<any, string[][]> }>>(schema.validateAsync(value, { warnings: true }));
expect.error<Promise<TResult>>(schema.validateAsync(value, { artifacts: true, warnings: true }));
expect.type<Promise<TResult>>(schema.validateAsync(value, { artifacts: false }));
expect.type<Promise<TResult>>(schema.validateAsync(value, { warnings: false }));
expect.type<Promise<TResult>>(schema.validateAsync(value, { artifacts: false, warnings: false }));

const falsyValue = { username: 'example' };
result = schema.validate(falsyValue);
if (!result.error) {
Expand Down

0 comments on commit 96bbfdd

Please sign in to comment.