mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-10-06 07:47:04 +00:00
Support Yup required/notRequired derived types (#36155)
* Support undefined with notRequired() * ArraySchema<T> instead of this * children can be undefined * Export InferType<T> * Support undefined and null for arrays * Reduced types count and dupicated code for arrays * Added boolean overloads
This commit is contained in:
committed by
Daniel Rosenwasser
parent
dfd9f6e84a
commit
a9e638dbda
Vendored
+97
-26
@@ -72,10 +72,6 @@ export interface Schema<T> {
|
||||
withMutation(fn: (current: this) => void): void;
|
||||
default(value: any): this;
|
||||
default(): T;
|
||||
nullable(isNullable?: true): Schema<T | null>;
|
||||
nullable(isNullable: false): Schema<Exclude<T, null>>;
|
||||
required(message?: TestOptionsMessage): this;
|
||||
notRequired(): this;
|
||||
typeError(message?: TestOptionsMessage): this;
|
||||
oneOf(arrayOfValues: any[], message?: TestOptionsMessage): this;
|
||||
notOneOf(arrayOfValues: any[], message?: TestOptionsMessage): this;
|
||||
@@ -100,15 +96,20 @@ export interface MixedSchemaConstructor {
|
||||
new (options?: { type?: string; [key: string]: any }): MixedSchema;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-empty-interface
|
||||
export interface MixedSchema extends Schema<any> {}
|
||||
export interface MixedSchema<T = any> extends Schema<T> {
|
||||
nullable(isNullable?: true): MixedSchema<T | null>;
|
||||
nullable(isNullable: false): MixedSchema<Exclude<T, null>>;
|
||||
nullable(isNullable?: boolean): MixedSchema<T>;
|
||||
required(message?: TestOptionsMessage): MixedSchema<Exclude<T, undefined>>;
|
||||
notRequired(): MixedSchema<T | undefined>;
|
||||
}
|
||||
|
||||
export interface StringSchemaConstructor {
|
||||
(): StringSchema;
|
||||
new (): StringSchema;
|
||||
}
|
||||
|
||||
export interface StringSchema<T extends string | null = string>
|
||||
export interface StringSchema<T extends string | null | undefined = string>
|
||||
extends Schema<T> {
|
||||
length(limit: number | Ref, message?: TestOptionsMessage): StringSchema<T>;
|
||||
min(limit: number | Ref, message?: TestOptionsMessage): StringSchema<T>;
|
||||
@@ -127,6 +128,9 @@ export interface StringSchema<T extends string | null = string>
|
||||
uppercase(message?: TestOptionsMessage): StringSchema<T>;
|
||||
nullable(isNullable?: true): StringSchema<T | null>;
|
||||
nullable(isNullable: false): StringSchema<Exclude<T, null>>;
|
||||
nullable(isNullable?: boolean): StringSchema<T>;
|
||||
required(message?: TestOptionsMessage): StringSchema<Exclude<T, undefined>>;
|
||||
notRequired(): StringSchema<T | undefined>;
|
||||
}
|
||||
|
||||
export interface NumberSchemaConstructor {
|
||||
@@ -134,7 +138,7 @@ export interface NumberSchemaConstructor {
|
||||
new (): NumberSchema;
|
||||
}
|
||||
|
||||
export interface NumberSchema<T extends number | null = number>
|
||||
export interface NumberSchema<T extends number | null | undefined = number>
|
||||
extends Schema<T> {
|
||||
min(limit: number | Ref, message?: TestOptionsMessage): NumberSchema<T>;
|
||||
max(limit: number | Ref, message?: TestOptionsMessage): NumberSchema<T>;
|
||||
@@ -153,6 +157,9 @@ export interface NumberSchema<T extends number | null = number>
|
||||
round(type: "floor" | "ceil" | "trunc" | "round"): NumberSchema<T>;
|
||||
nullable(isNullable?: true): NumberSchema<T | null>;
|
||||
nullable(isNullable: false): NumberSchema<Exclude<T, null>>;
|
||||
nullable(isNullable?: boolean): NumberSchema<T>;
|
||||
required(message?: TestOptionsMessage): NumberSchema<Exclude<T, undefined>>;
|
||||
notRequired(): NumberSchema<T | undefined>;
|
||||
}
|
||||
|
||||
export interface BooleanSchemaConstructor {
|
||||
@@ -160,11 +167,15 @@ export interface BooleanSchemaConstructor {
|
||||
new (): BooleanSchema;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-empty-interface
|
||||
export interface BooleanSchema<T extends boolean | null = boolean>
|
||||
export interface BooleanSchema<T extends boolean | null | undefined = boolean>
|
||||
extends Schema<T> {
|
||||
nullable(isNullable?: true): BooleanSchema<T | null>;
|
||||
nullable(isNullable: false): BooleanSchema<Exclude<T, null>>;
|
||||
nullable(isNullable?: boolean): BooleanSchema<T>;
|
||||
required(
|
||||
message?: TestOptionsMessage
|
||||
): BooleanSchema<Exclude<T, undefined>>;
|
||||
notRequired(): BooleanSchema<T | undefined>;
|
||||
}
|
||||
|
||||
export interface DateSchemaConstructor {
|
||||
@@ -172,7 +183,8 @@ export interface DateSchemaConstructor {
|
||||
new (): DateSchema;
|
||||
}
|
||||
|
||||
export interface DateSchema<T extends Date | null = Date> extends Schema<T> {
|
||||
export interface DateSchema<T extends Date | null | undefined = Date>
|
||||
extends Schema<T> {
|
||||
min(
|
||||
limit: Date | string | Ref,
|
||||
message?: TestOptionsMessage
|
||||
@@ -183,6 +195,9 @@ export interface DateSchema<T extends Date | null = Date> extends Schema<T> {
|
||||
): DateSchema<T>;
|
||||
nullable(isNullable?: true): DateSchema<T | null>;
|
||||
nullable(isNullable: false): DateSchema<Exclude<T, null>>;
|
||||
nullable(isNullable?: boolean): DateSchema<T>;
|
||||
required(message?: TestOptionsMessage): DateSchema<Exclude<T, undefined>>;
|
||||
notRequired(): DateSchema<T | undefined>;
|
||||
}
|
||||
|
||||
export interface ArraySchemaConstructor {
|
||||
@@ -190,17 +205,52 @@ export interface ArraySchemaConstructor {
|
||||
new (): ArraySchema<{}>;
|
||||
}
|
||||
|
||||
export interface ArraySchema<T> extends Schema<T[]> {
|
||||
of<U>(type: Schema<U>): ArraySchema<U>;
|
||||
min(limit: number | Ref, message?: TestOptionsMessage): ArraySchema<T>;
|
||||
max(limit: number | Ref, message?: TestOptionsMessage): ArraySchema<T>;
|
||||
ensure(): ArraySchema<T>;
|
||||
compact(
|
||||
rejector?: (value: T, index: number, array: T[]) => boolean
|
||||
): ArraySchema<T>;
|
||||
interface BasicArraySchema<T extends any[] | null | undefined>
|
||||
extends Schema<T> {
|
||||
min(limit: number | Ref, message?: TestOptionsMessage): this;
|
||||
max(limit: number | Ref, message?: TestOptionsMessage): this;
|
||||
ensure(): this;
|
||||
compact(rejector?: (value: T, index: number, array: T[]) => boolean): this;
|
||||
}
|
||||
|
||||
export type ObjectSchemaDefinition<T extends object> = {
|
||||
export interface NotRequiredNullableArraySchema<T>
|
||||
extends BasicArraySchema<T[] | null | undefined> {
|
||||
of<U>(type: Schema<U>): NotRequiredNullableArraySchema<U>;
|
||||
nullable(isNullable?: true): NotRequiredNullableArraySchema<T>;
|
||||
nullable(isNullable: false): NotRequiredArraySchema<T>;
|
||||
nullable(isNullable?: boolean): ArraySchema<T>;
|
||||
required(message?: TestOptionsMessage): NullableArraySchema<T>;
|
||||
notRequired(): NotRequiredNullableArraySchema<T>;
|
||||
}
|
||||
|
||||
export interface NullableArraySchema<T> extends BasicArraySchema<T[] | null> {
|
||||
of<U>(type: Schema<U>): NullableArraySchema<U>;
|
||||
nullable(isNullable?: true): NullableArraySchema<T>;
|
||||
nullable(isNullable: false): ArraySchema<T>;
|
||||
nullable(isNullable?: boolean): ArraySchema<T>;
|
||||
required(message?: TestOptionsMessage): NullableArraySchema<T>;
|
||||
notRequired(): NotRequiredNullableArraySchema<T>;
|
||||
}
|
||||
|
||||
export interface NotRequiredArraySchema<T>
|
||||
extends BasicArraySchema<T[] | undefined> {
|
||||
of<U>(type: Schema<U>): NotRequiredArraySchema<U>;
|
||||
nullable(isNullable?: true): NotRequiredNullableArraySchema<T>;
|
||||
nullable(isNullable: false): NotRequiredArraySchema<T>;
|
||||
nullable(isNullable: boolean): ArraySchema<T>;
|
||||
required(message?: TestOptionsMessage): ArraySchema<T>;
|
||||
notRequired(): NotRequiredArraySchema<T>;
|
||||
}
|
||||
|
||||
export interface ArraySchema<T> extends BasicArraySchema<T[]> {
|
||||
of<U>(type: Schema<U>): ArraySchema<U>;
|
||||
nullable(isNullable?: true): NullableArraySchema<T>;
|
||||
nullable(isNullable: false | boolean): ArraySchema<T>;
|
||||
required(message?: TestOptionsMessage): ArraySchema<T>;
|
||||
notRequired(): NotRequiredArraySchema<T>;
|
||||
}
|
||||
|
||||
export type ObjectSchemaDefinition<T extends object | null | undefined> = {
|
||||
[field in keyof T]: Schema<T[field]> | Ref
|
||||
};
|
||||
|
||||
@@ -209,7 +259,7 @@ export type ObjectSchemaDefinition<T extends object> = {
|
||||
* This is conducive to the functionality of
|
||||
* [yup's `object.shape()` method](https://www.npmjs.com/package/yup#objectshapefields-object-nosortedges-arraystring-string-schema).
|
||||
*/
|
||||
export type Shape<T extends object, U extends object> = {
|
||||
export type Shape<T extends object | null | undefined, U extends object> = {
|
||||
[P in keyof T]: P extends keyof U ? U[P] : T[P]
|
||||
} &
|
||||
U;
|
||||
@@ -219,7 +269,8 @@ export interface ObjectSchemaConstructor {
|
||||
new (): ObjectSchema<{}>;
|
||||
}
|
||||
|
||||
export interface ObjectSchema<T extends object> extends Schema<T> {
|
||||
export interface ObjectSchema<T extends object | null | undefined = object>
|
||||
extends Schema<T> {
|
||||
shape<U extends object>(
|
||||
fields: ObjectSchemaDefinition<U>,
|
||||
noSortEdges?: Array<[string, string]>
|
||||
@@ -232,6 +283,11 @@ export interface ObjectSchema<T extends object> extends Schema<T> {
|
||||
transformKeys(callback: (key: any) => any): void;
|
||||
camelCase(): ObjectSchema<T>;
|
||||
constantCase(): ObjectSchema<T>;
|
||||
nullable(isNullable?: true): ObjectSchema<T | null>;
|
||||
nullable(isNullable: false): ObjectSchema<Exclude<T, null>>;
|
||||
nullable(isNullable?: boolean): ObjectSchema<T>;
|
||||
required(message?: TestOptionsMessage): ObjectSchema<Exclude<T, undefined>>;
|
||||
notRequired(): ObjectSchema<T | undefined>;
|
||||
}
|
||||
|
||||
export type TransformFunction<T> = (
|
||||
@@ -257,13 +313,13 @@ export type WhenOptionsBuilderObjectIs =
|
||||
|
||||
export type WhenOptionsBuilderObject =
|
||||
| {
|
||||
is: WhenOptionsBuilderObjectIs;
|
||||
then: any;
|
||||
otherwise: any
|
||||
is: WhenOptionsBuilderObjectIs;
|
||||
then: any;
|
||||
otherwise: any;
|
||||
}
|
||||
| object;
|
||||
|
||||
export type WhenOptions<T> =
|
||||
export type WhenOptions<T> =
|
||||
| WhenOptionsBuilderFunction<T>
|
||||
| WhenOptionsBuilderObject;
|
||||
|
||||
@@ -435,3 +491,18 @@ export interface LocaleObject {
|
||||
array?: { [key in keyof ArraySchema<any>]?: string };
|
||||
object?: { [key in keyof ObjectSchema<any>]?: string };
|
||||
}
|
||||
|
||||
export type InferType<T> = T extends Schema<infer P>
|
||||
? InnerInferType<P>
|
||||
: never;
|
||||
|
||||
// Shut off automatic exporting after this statement
|
||||
export {};
|
||||
|
||||
type KeyOfUndefined<T> = {
|
||||
[P in keyof T]-?: undefined extends T[P] ? P : never
|
||||
}[keyof T];
|
||||
|
||||
type RequiredProps<T> = Pick<T, Exclude<keyof T, KeyOfUndefined<T>>>;
|
||||
type NotRequiredProps<T> = Partial<Pick<T, KeyOfUndefined<T>>>;
|
||||
type InnerInferType<T> = NotRequiredProps<T> & RequiredProps<T>;
|
||||
|
||||
+254
-243
@@ -1,4 +1,4 @@
|
||||
import * as yup from "yup";
|
||||
import * as yup from 'yup';
|
||||
|
||||
// tslint:disable-next-line:no-duplicate-imports
|
||||
import {
|
||||
@@ -14,48 +14,40 @@ import {
|
||||
ValidateOptions,
|
||||
NumberSchema,
|
||||
TestContext,
|
||||
LocaleObject
|
||||
} from "yup";
|
||||
LocaleObject,
|
||||
} from 'yup';
|
||||
|
||||
// reach function
|
||||
const schema1 = yup.object().shape({
|
||||
nested: yup.object().shape({
|
||||
arr: yup.array().of(yup.object().shape({ num: yup.number().max(4) }))
|
||||
})
|
||||
arr: yup.array().of(yup.object().shape({ num: yup.number().max(4) })),
|
||||
}),
|
||||
});
|
||||
reach(schema1, "nested.arr.num");
|
||||
reach(schema1, "nested.arr[].num");
|
||||
reach(schema1, 'nested.arr.num');
|
||||
reach(schema1, 'nested.arr[].num');
|
||||
|
||||
// isSchema function
|
||||
const isSchemaResult1: boolean = isSchema(schema1);
|
||||
const isSchemaResult2: boolean = isSchema({});
|
||||
|
||||
// addMethod function
|
||||
yup.addMethod<NumberSchema>(yup.number, "minimum", function(
|
||||
this,
|
||||
minValue: number,
|
||||
message: string
|
||||
) {
|
||||
yup.addMethod<NumberSchema>(yup.number, 'minimum', function(this, minValue: number, message: string) {
|
||||
return this.min(minValue, message);
|
||||
});
|
||||
yup.addMethod(yup.date, "newMethod", function(
|
||||
this: yup.DateSchema,
|
||||
date: Date,
|
||||
message?: string
|
||||
) {
|
||||
yup.addMethod(yup.date, 'newMethod', function(this: yup.DateSchema, date: Date, message?: string) {
|
||||
return this.max(date, message);
|
||||
});
|
||||
|
||||
// ref function
|
||||
const schema2 = yup.object().shape({
|
||||
baz: yup.ref("foo.bar"),
|
||||
baz: yup.ref('foo.bar'),
|
||||
foo: yup.object().shape({
|
||||
bar: yup.string()
|
||||
bar: yup.string(),
|
||||
}),
|
||||
x: yup.ref("$x")
|
||||
x: yup.ref('$x'),
|
||||
});
|
||||
|
||||
let ref: yup.Ref = yup.ref("foo.bar");
|
||||
let ref: yup.Ref = yup.ref('foo.bar');
|
||||
|
||||
// $ExpectError
|
||||
ref = {};
|
||||
@@ -64,18 +56,18 @@ ref = {};
|
||||
ref = { __isYupRef: true };
|
||||
|
||||
// cast function
|
||||
schema2.cast({ foo: { bar: "boom" } }, { context: { x: 5 } });
|
||||
schema2.cast({ foo: { bar: 'boom' } }, { context: { x: 5 } });
|
||||
|
||||
// lazy function
|
||||
const node: ObjectSchema<any> = yup.object().shape({
|
||||
id: yup.number(),
|
||||
child: yup.lazy(() => node.default(undefined))
|
||||
child: yup.lazy(() => node.default(undefined)),
|
||||
});
|
||||
const renderable = yup.lazy(value => {
|
||||
switch (typeof value) {
|
||||
case "number":
|
||||
case 'number':
|
||||
return yup.number();
|
||||
case "string":
|
||||
case 'string':
|
||||
return yup.string();
|
||||
default:
|
||||
return yup.mixed();
|
||||
@@ -85,63 +77,56 @@ const renderables = yup.array().of(renderable);
|
||||
|
||||
// ValidationError static methods
|
||||
// $ExpectType boolean
|
||||
ValidationError.isError(new ValidationError("error", "value", "path"));
|
||||
ValidationError.isError(new ValidationError('error', 'value', 'path'));
|
||||
// $ExpectType string | ((params?: any) => string)
|
||||
ValidationError.formatError("error", { path: "path" });
|
||||
ValidationError.formatError("error");
|
||||
ValidationError.formatError(() => "error");
|
||||
ValidationError.formatError(() => "error", { path: "path" });
|
||||
ValidationError.formatError('error', { path: 'path' });
|
||||
ValidationError.formatError('error');
|
||||
ValidationError.formatError(() => 'error');
|
||||
ValidationError.formatError(() => 'error', { path: 'path' });
|
||||
|
||||
// ValidationError
|
||||
let error: ValidationError = new yup.ValidationError("error", "value", "path");
|
||||
error = new yup.ValidationError(["error", "error2"], true, "path");
|
||||
error = new yup.ValidationError(["error", "error2"], 5, "path");
|
||||
error = new yup.ValidationError(["error", "error2"], { name: "value" }, "path");
|
||||
error = new yup.ValidationError(
|
||||
["error", "error2"],
|
||||
{ name: "value" },
|
||||
"path",
|
||||
"type"
|
||||
);
|
||||
let error: ValidationError = new yup.ValidationError('error', 'value', 'path');
|
||||
error = new yup.ValidationError(['error', 'error2'], true, 'path');
|
||||
error = new yup.ValidationError(['error', 'error2'], 5, 'path');
|
||||
error = new yup.ValidationError(['error', 'error2'], { name: 'value' }, 'path');
|
||||
error = new yup.ValidationError(['error', 'error2'], { name: 'value' }, 'path', 'type');
|
||||
error = {
|
||||
name: "ValidationError",
|
||||
message: "error",
|
||||
path: "path",
|
||||
errors: ["error"],
|
||||
inner: [new yup.ValidationError("error", true, "path")],
|
||||
type: "date",
|
||||
value: { start: "2017-11-10" }
|
||||
name: 'ValidationError',
|
||||
message: 'error',
|
||||
path: 'path',
|
||||
errors: ['error'],
|
||||
inner: [new yup.ValidationError('error', true, 'path')],
|
||||
type: 'date',
|
||||
value: { start: '2017-11-10' },
|
||||
};
|
||||
error.value = "value";
|
||||
error.value = 'value';
|
||||
error.value = true;
|
||||
error.value = 5;
|
||||
error.value = { name: "value" };
|
||||
error.value = { name: 'value' };
|
||||
error.type = {};
|
||||
error.type = [];
|
||||
error.errors = ["error"];
|
||||
error.errors = ['error'];
|
||||
|
||||
// mixed
|
||||
let mixed: MixedSchema = yup.mixed();
|
||||
mixed.clone();
|
||||
mixed.label("label");
|
||||
mixed.meta({ meta: "value" });
|
||||
mixed.label('label');
|
||||
mixed.meta({ meta: 'value' });
|
||||
mixed.describe().label;
|
||||
mixed.describe().meta;
|
||||
mixed.describe().tests;
|
||||
mixed.describe().type;
|
||||
mixed.concat(yup.string());
|
||||
mixed.validate({});
|
||||
mixed.validate({ hello: "world" }, { strict: true }).then(value => value);
|
||||
mixed.validateSync({ hello: "world" }, { strict: true });
|
||||
mixed.validateAt("path", {}, { strict: true, context: {} });
|
||||
mixed
|
||||
.validateAt("path", {}, { strict: true, context: {} })
|
||||
.then(value => value);
|
||||
mixed.validateSyncAt("path", {}, { strict: true, context: {} });
|
||||
mixed.validate({ hello: 'world' }, { strict: true }).then(value => value);
|
||||
mixed.validateSync({ hello: 'world' }, { strict: true });
|
||||
mixed.validateAt('path', {}, { strict: true, context: {} });
|
||||
mixed.validateAt('path', {}, { strict: true, context: {} }).then(value => value);
|
||||
mixed.validateSyncAt('path', {}, { strict: true, context: {} });
|
||||
mixed.isValid(undefined, (valid: true) => true);
|
||||
mixed.isValid({ hello: "world" }).then(valid => valid);
|
||||
mixed.isValid({ hello: 'world' }).then(valid => valid);
|
||||
mixed.cast({});
|
||||
mixed.isType("hello");
|
||||
mixed.isType('hello');
|
||||
mixed.strict(true);
|
||||
mixed.strip(true);
|
||||
mixed.withMutation(schema => {});
|
||||
@@ -151,53 +136,43 @@ mixed.default();
|
||||
mixed.nullable(true);
|
||||
mixed.nullable();
|
||||
mixed.required();
|
||||
mixed.required("Foo");
|
||||
mixed.required(() => "Foo");
|
||||
mixed.notRequired(); // $ExpectType MixedSchema
|
||||
mixed.typeError("type error");
|
||||
mixed.typeError(() => "type error");
|
||||
mixed.oneOf(["hello", "world"], "message");
|
||||
mixed.oneOf(["hello", "world"], () => "message");
|
||||
mixed.notOneOf(["hello", "world"], "message");
|
||||
mixed.notOneOf(["hello", "world"], () => "message");
|
||||
mixed.when("isBig", {
|
||||
mixed.required('Foo');
|
||||
mixed.required(() => 'Foo');
|
||||
mixed.notRequired(); // $ExpectType MixedSchema<any>
|
||||
mixed.typeError('type error');
|
||||
mixed.typeError(() => 'type error');
|
||||
mixed.oneOf(['hello', 'world'], 'message');
|
||||
mixed.oneOf(['hello', 'world'], () => 'message');
|
||||
mixed.notOneOf(['hello', 'world'], 'message');
|
||||
mixed.notOneOf(['hello', 'world'], () => 'message');
|
||||
mixed.when('isBig', {
|
||||
is: value => true,
|
||||
then: yup.number().min(5),
|
||||
otherwise: yup.number().min(0)
|
||||
otherwise: yup.number().min(0),
|
||||
});
|
||||
mixed.when(["isBig", "isSpecial"], {
|
||||
mixed.when(['isBig', 'isSpecial'], {
|
||||
is: (isBig, isSpecial) => isBig && isSpecial,
|
||||
then: yup.number().min(5),
|
||||
otherwise: yup.number().min(0),
|
||||
});
|
||||
mixed
|
||||
.when("isBig", {
|
||||
.when('isBig', {
|
||||
is: true,
|
||||
then: yup.number().min(5),
|
||||
otherwise: yup.number().min(0)
|
||||
otherwise: yup.number().min(0),
|
||||
})
|
||||
.when("$other", (value: any, schema: MixedSchema) =>
|
||||
value === 4 ? schema.required() : schema
|
||||
);
|
||||
.when('$other', (value: any, schema: MixedSchema) => (value === 4 ? schema.required() : schema));
|
||||
// tslint:disable-next-line:no-invalid-template-strings
|
||||
mixed.test("is-jimmy", "${path} is not Jimmy", value => value === "jimmy");
|
||||
mixed.test(
|
||||
"is-jimmy",
|
||||
({ path, value }) => `${path} has an error, it is ${value}`,
|
||||
value => value === "jimmy"
|
||||
);
|
||||
mixed.test('is-jimmy', '${path} is not Jimmy', value => value === 'jimmy');
|
||||
mixed.test('is-jimmy', ({ path, value }) => `${path} has an error, it is ${value}`, value => value === 'jimmy');
|
||||
mixed.test({
|
||||
name: "lessThan5",
|
||||
name: 'lessThan5',
|
||||
exclusive: true,
|
||||
// tslint:disable-next-line:no-invalid-template-strings
|
||||
message: "${path} must be less than 5 characters",
|
||||
test: value => value == null || value.length <= 5
|
||||
message: '${path} must be less than 5 characters',
|
||||
test: value => value == null || value.length <= 5,
|
||||
});
|
||||
mixed.test(
|
||||
"with-promise",
|
||||
"It contains invalid value",
|
||||
value => new Promise(resolve => true)
|
||||
);
|
||||
mixed.test('with-promise', 'It contains invalid value', value => new Promise(resolve => true));
|
||||
const testContext = function(this: TestContext) {
|
||||
// $ExpectType string
|
||||
this.path;
|
||||
@@ -210,50 +185,38 @@ const testContext = function(this: TestContext) {
|
||||
// $ExpectType (value: any) => any
|
||||
this.resolve;
|
||||
// $ExpectType ValidationError
|
||||
this.createError({ path: "1", message: "1" });
|
||||
this.createError({ path: '1', message: '1' });
|
||||
// $ExpectType ValidationError
|
||||
this.createError({ message: "1" });
|
||||
this.createError({ message: '1' });
|
||||
// $ExpectType ValidationError
|
||||
this.createError({ path: "1" });
|
||||
this.createError({ path: '1' });
|
||||
// $ExpectType ValidationError
|
||||
this.createError();
|
||||
return true;
|
||||
};
|
||||
mixed.test("with-context", "it uses function context", testContext);
|
||||
mixed.test('with-context', 'it uses function context', testContext);
|
||||
mixed.test({
|
||||
test: testContext
|
||||
test: testContext,
|
||||
});
|
||||
|
||||
// Async ValidationError
|
||||
const asyncValidationErrorTest = function(
|
||||
this: TestContext
|
||||
): Promise<ValidationError> {
|
||||
return new Promise(resolve =>
|
||||
resolve(this.createError({ path: "testPath", message: "testMessage" }))
|
||||
);
|
||||
const asyncValidationErrorTest = function(this: TestContext): Promise<ValidationError> {
|
||||
return new Promise(resolve => resolve(this.createError({ path: 'testPath', message: 'testMessage' })));
|
||||
};
|
||||
|
||||
mixed.test(
|
||||
"async-validation-error",
|
||||
"Returns async ValidationError",
|
||||
asyncValidationErrorTest
|
||||
);
|
||||
mixed.test('async-validation-error', 'Returns async ValidationError', asyncValidationErrorTest);
|
||||
mixed.test({
|
||||
test: asyncValidationErrorTest
|
||||
test: asyncValidationErrorTest,
|
||||
});
|
||||
|
||||
// Sync ValidationError
|
||||
const syncValidationErrorTest = function(this: TestContext): ValidationError {
|
||||
return this.createError({ path: "testPath", message: "testMessage" });
|
||||
return this.createError({ path: 'testPath', message: 'testMessage' });
|
||||
};
|
||||
|
||||
mixed.test(
|
||||
"sync-validation-error",
|
||||
"Returns sync ValidationError",
|
||||
syncValidationErrorTest
|
||||
);
|
||||
mixed.test('sync-validation-error', 'Returns sync ValidationError', syncValidationErrorTest);
|
||||
mixed.test({
|
||||
test: syncValidationErrorTest
|
||||
test: syncValidationErrorTest,
|
||||
});
|
||||
|
||||
yup.string().transform(function(this, value: any, originalvalue: any) {
|
||||
@@ -266,7 +229,7 @@ mixed = new ExtendsMixed();
|
||||
|
||||
class ExtendsMixed2 extends yup.mixed {
|
||||
constructor() {
|
||||
super({ type: "CustomType" });
|
||||
super({ type: 'CustomType' });
|
||||
}
|
||||
}
|
||||
mixed = new ExtendsMixed2();
|
||||
@@ -277,79 +240,79 @@ mixed = new ExtendsMixed2();
|
||||
class DateSchema extends yup.date {
|
||||
isWednesday(message?: string): DateSchema {
|
||||
return this.clone().test({
|
||||
name: "Wednesday",
|
||||
name: 'Wednesday',
|
||||
// tslint:disable-next-line:no-invalid-template-strings
|
||||
message: message || "${path} must be Wednesday",
|
||||
test: value => true /* Check that day is Wednesday */
|
||||
message: message || '${path} must be Wednesday',
|
||||
test: value => true /* Check that day is Wednesday */,
|
||||
});
|
||||
}
|
||||
}
|
||||
yup.object()
|
||||
.shape({
|
||||
startDate: new DateSchema().isWednesday().required()
|
||||
startDate: new DateSchema().isWednesday().required(),
|
||||
})
|
||||
.isValidSync({
|
||||
startDate: "2017-11-29"
|
||||
startDate: '2017-11-29',
|
||||
});
|
||||
|
||||
// String schema
|
||||
const strSchema = yup.string(); // $ExpectType StringSchema<string>
|
||||
strSchema.isValid("hello"); // => true
|
||||
strSchema.isValid('hello'); // => true
|
||||
strSchema.required();
|
||||
strSchema.required("req");
|
||||
strSchema.required(() => "req");
|
||||
strSchema.length(5, "message");
|
||||
strSchema.length(5, () => "message");
|
||||
strSchema.min(5, "message");
|
||||
strSchema.min(5, () => "message");
|
||||
strSchema.max(5, "message");
|
||||
strSchema.max(5, () => "message");
|
||||
strSchema.required('req');
|
||||
strSchema.required(() => 'req');
|
||||
strSchema.length(5, 'message');
|
||||
strSchema.length(5, () => 'message');
|
||||
strSchema.min(5, 'message');
|
||||
strSchema.min(5, () => 'message');
|
||||
strSchema.max(5, 'message');
|
||||
strSchema.max(5, () => 'message');
|
||||
strSchema.matches(/(hi|bye)/);
|
||||
strSchema.matches(/(hi|bye)/, "invalid");
|
||||
strSchema.matches(/(hi|bye)/, () => "invalid");
|
||||
strSchema.matches(/(hi|bye)/, 'invalid');
|
||||
strSchema.matches(/(hi|bye)/, () => 'invalid');
|
||||
strSchema.email();
|
||||
strSchema.email("invalid");
|
||||
strSchema.email(() => "invalid");
|
||||
strSchema.email('invalid');
|
||||
strSchema.email(() => 'invalid');
|
||||
strSchema.url();
|
||||
strSchema.url("bad url");
|
||||
strSchema.url(() => "bad url");
|
||||
strSchema.url('bad url');
|
||||
strSchema.url(() => 'bad url');
|
||||
strSchema.ensure();
|
||||
strSchema.trim();
|
||||
strSchema.trim("trimmed");
|
||||
strSchema.trim(() => "trimmed");
|
||||
strSchema.trim('trimmed');
|
||||
strSchema.trim(() => 'trimmed');
|
||||
strSchema.lowercase();
|
||||
strSchema.lowercase("lower");
|
||||
strSchema.lowercase(() => "lower");
|
||||
strSchema.lowercase('lower');
|
||||
strSchema.lowercase(() => 'lower');
|
||||
strSchema.uppercase();
|
||||
strSchema.uppercase("upper");
|
||||
strSchema.uppercase(() => "upper");
|
||||
strSchema.uppercase('upper');
|
||||
strSchema.uppercase(() => 'upper');
|
||||
|
||||
// Number schema
|
||||
const numSchema = yup.number(); // $ExpectType NumberSchema<number>
|
||||
numSchema.isValid(10); // => true
|
||||
numSchema.min(5);
|
||||
numSchema.min(5, "message");
|
||||
numSchema.min(5, () => "message");
|
||||
numSchema.min(5, 'message');
|
||||
numSchema.min(5, () => 'message');
|
||||
numSchema.max(5);
|
||||
numSchema.max(5, "message");
|
||||
numSchema.max(5, () => "message");
|
||||
numSchema.max(5, 'message');
|
||||
numSchema.max(5, () => 'message');
|
||||
numSchema.positive();
|
||||
numSchema.positive("pos");
|
||||
numSchema.positive(() => "pos");
|
||||
numSchema.positive('pos');
|
||||
numSchema.positive(() => 'pos');
|
||||
numSchema.negative();
|
||||
numSchema.negative("neg");
|
||||
numSchema.negative(() => "neg");
|
||||
numSchema.negative('neg');
|
||||
numSchema.negative(() => 'neg');
|
||||
numSchema.lessThan(5);
|
||||
numSchema.lessThan(5, "lt");
|
||||
numSchema.lessThan(5, () => "lt");
|
||||
numSchema.lessThan(5, 'lt');
|
||||
numSchema.lessThan(5, () => 'lt');
|
||||
numSchema.moreThan(5);
|
||||
numSchema.moreThan(5, "mt");
|
||||
numSchema.moreThan(5, () => "mt");
|
||||
numSchema.moreThan(5, 'mt');
|
||||
numSchema.moreThan(5, () => 'mt');
|
||||
numSchema.integer();
|
||||
numSchema.integer("int");
|
||||
numSchema.integer(() => "int");
|
||||
numSchema.integer('int');
|
||||
numSchema.integer(() => 'int');
|
||||
numSchema.truncate();
|
||||
numSchema.round("floor");
|
||||
numSchema.round('floor');
|
||||
numSchema
|
||||
.validate(5, { strict: true })
|
||||
.then(value => value)
|
||||
@@ -363,30 +326,30 @@ boolSchema.isValid(true); // => true
|
||||
const dateSchema = yup.date();
|
||||
dateSchema.isValid(new Date()); // => true
|
||||
dateSchema.min(new Date());
|
||||
dateSchema.min("2017-11-12");
|
||||
dateSchema.min(new Date(), "message");
|
||||
dateSchema.min("2017-11-12", "message");
|
||||
dateSchema.min("2017-11-12", () => "message");
|
||||
dateSchema.min('2017-11-12');
|
||||
dateSchema.min(new Date(), 'message');
|
||||
dateSchema.min('2017-11-12', 'message');
|
||||
dateSchema.min('2017-11-12', () => 'message');
|
||||
dateSchema.max(new Date());
|
||||
dateSchema.max("2017-11-12");
|
||||
dateSchema.max(new Date(), "message");
|
||||
dateSchema.max("2017-11-12", "message");
|
||||
dateSchema.max("2017-11-12", () => "message");
|
||||
dateSchema.max('2017-11-12');
|
||||
dateSchema.max(new Date(), 'message');
|
||||
dateSchema.max('2017-11-12', 'message');
|
||||
dateSchema.max('2017-11-12', () => 'message');
|
||||
|
||||
// Array Schema
|
||||
const arrSchema = yup.array().of(yup.number().min(2));
|
||||
arrSchema.isValid([2, 3]); // => true
|
||||
arrSchema.isValid([1, -24]); // => false
|
||||
arrSchema.required();
|
||||
arrSchema.required("req");
|
||||
arrSchema.required(() => "req");
|
||||
arrSchema.required('req');
|
||||
arrSchema.required(() => 'req');
|
||||
arrSchema.ensure();
|
||||
arrSchema.max(5);
|
||||
arrSchema.max(5, "max");
|
||||
arrSchema.max(5, () => "max");
|
||||
arrSchema.max(5, 'max');
|
||||
arrSchema.max(5, () => 'max');
|
||||
arrSchema.min(5);
|
||||
arrSchema.min(5, "min");
|
||||
arrSchema.min(5, () => "min");
|
||||
arrSchema.min(5, 'min');
|
||||
arrSchema.min(5, () => 'min');
|
||||
arrSchema.compact((value, index, array) => value === array[index]);
|
||||
|
||||
const arr = yup.array();
|
||||
@@ -404,48 +367,48 @@ const objSchema = yup.object().shape({
|
||||
.positive()
|
||||
.integer(),
|
||||
email: yup.string().email(),
|
||||
website: yup.string().url()
|
||||
website: yup.string().url(),
|
||||
});
|
||||
yup.object().shape({
|
||||
num: yup.number()
|
||||
num: yup.number(),
|
||||
});
|
||||
// or
|
||||
yup.object({
|
||||
num: yup.number()
|
||||
num: yup.number(),
|
||||
});
|
||||
|
||||
objSchema.from("prop", "myProp");
|
||||
objSchema.from("prop", "myProp", true);
|
||||
objSchema.from('prop', 'myProp');
|
||||
objSchema.from('prop', 'myProp', true);
|
||||
objSchema.noUnknown();
|
||||
objSchema.noUnknown(true);
|
||||
objSchema.noUnknown(true, "message");
|
||||
objSchema.noUnknown(true, () => "message");
|
||||
objSchema.noUnknown(true, 'message');
|
||||
objSchema.noUnknown(true, () => 'message');
|
||||
objSchema.transformKeys(key => key.toUpperCase());
|
||||
objSchema.camelCase();
|
||||
objSchema.constantCase();
|
||||
|
||||
const description: SchemaDescription = {
|
||||
type: "type",
|
||||
label: "label",
|
||||
meta: { key: "value" },
|
||||
tests: [{ name: "test1", params: {} }, { name: "test2", params: {} }],
|
||||
fields: { key: "value" }
|
||||
type: 'type',
|
||||
label: 'label',
|
||||
meta: { key: 'value' },
|
||||
tests: [{ name: 'test1', params: {} }, { name: 'test2', params: {} }],
|
||||
fields: { key: 'value' },
|
||||
};
|
||||
|
||||
const testOptions: TestOptions = {
|
||||
name: "name",
|
||||
name: 'name',
|
||||
test: value => true,
|
||||
message: "validation error message",
|
||||
params: { param1: "value" },
|
||||
exclusive: true
|
||||
message: 'validation error message',
|
||||
params: { param1: 'value' },
|
||||
exclusive: true,
|
||||
};
|
||||
|
||||
const testOptionsWithPromise: TestOptions = {
|
||||
name: "name",
|
||||
name: 'name',
|
||||
test: value => new Promise(resolve => true),
|
||||
message: "validation error message",
|
||||
params: { param1: "value" },
|
||||
exclusive: true
|
||||
message: 'validation error message',
|
||||
params: { param1: 'value' },
|
||||
exclusive: true,
|
||||
};
|
||||
|
||||
const validateOptions: ValidateOptions = {
|
||||
@@ -454,45 +417,40 @@ const validateOptions: ValidateOptions = {
|
||||
stripUnknown: true,
|
||||
recursive: true,
|
||||
context: {
|
||||
key: "value"
|
||||
}
|
||||
key: 'value',
|
||||
},
|
||||
};
|
||||
|
||||
const localeNotType1: LocaleObject = {
|
||||
mixed: {
|
||||
required: "message",
|
||||
notType: "message"
|
||||
}
|
||||
required: 'message',
|
||||
notType: 'message',
|
||||
},
|
||||
};
|
||||
const localeNotType2: LocaleObject = {
|
||||
mixed: {
|
||||
required: "message",
|
||||
notType: () => "message"
|
||||
}
|
||||
required: 'message',
|
||||
notType: () => 'message',
|
||||
},
|
||||
};
|
||||
const localeNotType3: LocaleObject = {
|
||||
mixed: {
|
||||
required: "message",
|
||||
required: 'message',
|
||||
notType: _ref => {
|
||||
const isCast: boolean =
|
||||
_ref.originalValue != null && _ref.originalValue !== _ref.value;
|
||||
const finalPartOfTheMessage = isCast
|
||||
? ` (cast from the value '${_ref.originalValue}').`
|
||||
: ".";
|
||||
const isCast: boolean = _ref.originalValue != null && _ref.originalValue !== _ref.value;
|
||||
const finalPartOfTheMessage = isCast ? ` (cast from the value '${_ref.originalValue}').` : '.';
|
||||
|
||||
return (
|
||||
`${_ref.path} must be a '${_ref.type}'` +
|
||||
` but the final value was: '${
|
||||
_ref.value
|
||||
}'${finalPartOfTheMessage}`
|
||||
` but the final value was: '${_ref.value}'${finalPartOfTheMessage}`
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
yup.setLocale({
|
||||
number: { max: "Max message", min: "Min message" },
|
||||
string: { email: "String message" }
|
||||
number: { max: 'Max message', min: 'Min message' },
|
||||
string: { email: 'String message' },
|
||||
});
|
||||
|
||||
interface MyInterface {
|
||||
@@ -512,19 +470,19 @@ const typedSchema = yup.object<MyInterface>({
|
||||
numberField: yup.number().required(), // $ExpectType NumberSchema<number>
|
||||
subFields: yup
|
||||
.object({
|
||||
testField: yup.string().required()
|
||||
testField: yup.string().required(),
|
||||
})
|
||||
.required(),
|
||||
arrayField: yup.array(yup.string()).required() // $ExpectType ArraySchema<string>
|
||||
arrayField: yup.array(yup.string()).required(), // $ExpectType ArraySchema<string>
|
||||
});
|
||||
|
||||
const testObject: MyInterface = {
|
||||
stringField: "test1",
|
||||
stringField: 'test1',
|
||||
numberField: 123,
|
||||
subFields: {
|
||||
testField: "test2"
|
||||
testField: 'test2',
|
||||
},
|
||||
arrayField: ["hi"]
|
||||
arrayField: ['hi'],
|
||||
};
|
||||
|
||||
typedSchema.validateSync(testObject); // $ExpectType MyInterface
|
||||
@@ -547,19 +505,19 @@ interface ExpectedABC {
|
||||
}
|
||||
|
||||
const expectedAbc: ExpectedABC = {
|
||||
a: "qwerty",
|
||||
b: "asdfg",
|
||||
c: 123
|
||||
a: 'qwerty',
|
||||
b: 'asdfg',
|
||||
c: 123,
|
||||
};
|
||||
const actualAbc: yup.Shape<AB, BC> = expectedAbc;
|
||||
|
||||
const definitionAB: yup.ObjectSchemaDefinition<AB> = {
|
||||
a: yup.string(),
|
||||
b: yup.number()
|
||||
b: yup.number(),
|
||||
};
|
||||
const definitionBC: yup.ObjectSchemaDefinition<BC> = {
|
||||
b: yup.string(),
|
||||
c: yup.number()
|
||||
c: yup.number(),
|
||||
};
|
||||
const combinedSchema = yup.object(definitionAB).shape(definitionBC); // $ExpectType ObjectSchema<Shape<AB, BC>>
|
||||
|
||||
@@ -568,10 +526,10 @@ yup.object<MyInterface>({
|
||||
stringField: yup.string().required(),
|
||||
subFields: yup
|
||||
.object({
|
||||
testField: yup.string().required()
|
||||
testField: yup.string().required(),
|
||||
})
|
||||
.required(),
|
||||
arrayField: yup.array(yup.string()).required()
|
||||
arrayField: yup.array(yup.string()).required(),
|
||||
});
|
||||
|
||||
// $ExpectError
|
||||
@@ -580,17 +538,17 @@ yup.object<MyInterface>({
|
||||
numberField: yup.number().required(),
|
||||
subFields: yup
|
||||
.object({
|
||||
testField: yup.string().required()
|
||||
testField: yup.string().required(),
|
||||
})
|
||||
.required(),
|
||||
arrayField: yup.array(yup.string()).required()
|
||||
arrayField: yup.array(yup.string()).required(),
|
||||
});
|
||||
|
||||
// $ExpectError
|
||||
yup.object<MyInterface>({
|
||||
stringField: yup.string().required(),
|
||||
numberField: yup.number().required(),
|
||||
arrayField: yup.array(yup.string()).required()
|
||||
arrayField: yup.array(yup.string()).required(),
|
||||
});
|
||||
|
||||
// $ExpectError
|
||||
@@ -599,10 +557,10 @@ yup.object<MyInterface>({
|
||||
numberField: yup.number().required(),
|
||||
subFields: yup
|
||||
.object({
|
||||
testField: yup.number().required()
|
||||
testField: yup.number().required(),
|
||||
})
|
||||
.required(),
|
||||
arrayField: yup.array(yup.string()).required()
|
||||
arrayField: yup.array(yup.string()).required(),
|
||||
});
|
||||
|
||||
const personSchema = yup.object({
|
||||
@@ -610,48 +568,101 @@ const personSchema = yup.object({
|
||||
email: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.notRequired()
|
||||
.email(),
|
||||
birthDate: yup
|
||||
.date()
|
||||
.nullable()
|
||||
.notRequired()
|
||||
.min(new Date(1900, 0, 1)),
|
||||
canBeNull: yup.string().nullable(true), // $ExpectType StringSchema<string | null>
|
||||
isAlive: yup.boolean().nullable(),
|
||||
isAlive: yup
|
||||
.boolean()
|
||||
.nullable()
|
||||
.notRequired(),
|
||||
mustBeAString: yup
|
||||
.string()
|
||||
.nullable(true)
|
||||
.nullable(false),
|
||||
children: yup.array(yup.string()).nullable()
|
||||
.nullable(false)
|
||||
.notRequired()
|
||||
.required(),
|
||||
children: yup
|
||||
.array(yup.string())
|
||||
.nullable()
|
||||
.notRequired()
|
||||
.min(1),
|
||||
});
|
||||
|
||||
type Person = ReturnType<typeof personSchema.cast>;
|
||||
type Person = yup.InferType<typeof personSchema>;
|
||||
// Equivalent to:
|
||||
// type Person = {
|
||||
// firstName: string;
|
||||
// email: string | null;
|
||||
// birthDate: Date | null;
|
||||
// email?: string | null | undefined;
|
||||
// birthDate?: Date | null | undefined;
|
||||
// canBeNull: string | null;
|
||||
// isAlive: boolean | null;
|
||||
// isAlive: boolean | null | undefined;
|
||||
// mustBeAString: string;
|
||||
// children: string[] | null;
|
||||
// children?: string[] | null | undefined;
|
||||
// }
|
||||
|
||||
const minimalPerson: Person = {
|
||||
firstName: '',
|
||||
canBeNull: null,
|
||||
mustBeAString: '',
|
||||
};
|
||||
|
||||
const person: Person = {
|
||||
firstName: "",
|
||||
firstName: '',
|
||||
email: null,
|
||||
birthDate: null,
|
||||
canBeNull: null,
|
||||
isAlive: null,
|
||||
mustBeAString: "",
|
||||
children: null
|
||||
mustBeAString: '',
|
||||
children: null,
|
||||
};
|
||||
|
||||
person.email = "some@email.com";
|
||||
person.email = 'some@email.com';
|
||||
person.email = undefined;
|
||||
person.birthDate = new Date();
|
||||
person.isAlive = true;
|
||||
person.children = ["1", "2", "3"];
|
||||
person.isAlive = undefined;
|
||||
person.children = ['1', '2', '3'];
|
||||
person.children = undefined;
|
||||
|
||||
// $ExpectError
|
||||
person.firstName = null;
|
||||
// $ExpectError
|
||||
person.firstName = undefined;
|
||||
// $ExpectError
|
||||
person.mustBeAString = null;
|
||||
// $ExpectError
|
||||
person.mustBeAString = undefined;
|
||||
|
||||
const castPerson = personSchema.cast({});
|
||||
castPerson.firstName = '';
|
||||
// $ExpectError
|
||||
castPerson.firstName = null;
|
||||
// $ExpectError
|
||||
castPerson.firstName = undefined;
|
||||
castPerson.email = 'some@email.com';
|
||||
castPerson.email = null;
|
||||
castPerson.email = undefined;
|
||||
castPerson.birthDate = new Date();
|
||||
castPerson.birthDate = null;
|
||||
castPerson.birthDate = undefined;
|
||||
castPerson.isAlive = true;
|
||||
castPerson.isAlive = null;
|
||||
castPerson.isAlive = undefined;
|
||||
castPerson.children = ['1', '2', '3'];
|
||||
castPerson.children = null;
|
||||
castPerson.children = undefined;
|
||||
|
||||
function wrapper<T>(b: false, msx: MixedSchema<T>): MixedSchema<T>;
|
||||
function wrapper<T>(b: true, msx: MixedSchema<T>): MixedSchema<T | null>;
|
||||
|
||||
function wrapper<T>(b: boolean, msx: MixedSchema<T>): MixedSchema<T> {
|
||||
return msx.nullable(b);
|
||||
}
|
||||
|
||||
const resultingSchema1 = wrapper<string | number>(false, yup.mixed().oneOf(['1', 2])); // $ExpectType MixedSchema<string | number>
|
||||
const resultingSchema2 = wrapper<string | number>(true, yup.mixed().oneOf(['1', 2])); // $ExpectType MixedSchema<string | number | null>
|
||||
|
||||
Reference in New Issue
Block a user