mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2025-10-16 12:05:41 +00:00
* [yup] Fix locale object conditionals * Explicit locale objects and just use those where message is defined
501 lines
19 KiB
TypeScript
501 lines
19 KiB
TypeScript
// Type definitions for yup 0.26
|
|
// Project: https://github.com/jquense/yup
|
|
// Definitions by: Dominik Hardtke <https://github.com/dhardtke>,
|
|
// Vladyslav Tserman <https://github.com/vtserman>,
|
|
// Moreton Bay Regional Council <https://github.com/MoretonBayRC>,
|
|
// Sindre Seppola <https://github.com/sseppola>
|
|
// Yash Kulshrestha <https://github.com/YashdalfTheGray>
|
|
// Vincent Pizzo <https://github.com/vincentjames501>
|
|
// Robert Bullen <https://github.com/robertbullen>
|
|
// Yusuke Sato <https://github.com/sat0yu>
|
|
// Dan Rumney <https://github.com/dancrumb>
|
|
// Desmond Koh <https://github.com/deskoh>
|
|
// Maurice de Beijer <https://github.com/mauricedb>
|
|
// Kalley Powell <https://github.com/kalley>
|
|
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
// TypeScript Version: 2.8
|
|
|
|
export function reach<T>(schema: Schema<T>, path: string, value?: any, context?: any): Schema<T>;
|
|
export function addMethod<T extends Schema<any>>(
|
|
schemaCtor: AnySchemaConstructor,
|
|
name: string,
|
|
method: (this: T, ...args: any[]) => T,
|
|
): void;
|
|
export function ref(path: string, options?: { contextPrefix: string }): Ref;
|
|
export function lazy<T>(fn: (value: T) => Schema<T>): Lazy;
|
|
export function setLocale(customLocale: LocaleObject): void;
|
|
export function isSchema(obj: any): obj is Schema<any>;
|
|
|
|
export const mixed: MixedSchemaConstructor;
|
|
export const string: StringSchemaConstructor;
|
|
export const number: NumberSchemaConstructor;
|
|
export const boolean: BooleanSchemaConstructor;
|
|
export const bool: BooleanSchemaConstructor;
|
|
export const date: DateSchemaConstructor;
|
|
export const array: ArraySchemaConstructor;
|
|
export const object: ObjectSchemaConstructor;
|
|
|
|
export type AnySchemaConstructor =
|
|
| MixedSchemaConstructor
|
|
| StringSchemaConstructor
|
|
| NumberSchemaConstructor
|
|
| BooleanSchemaConstructor
|
|
| DateSchemaConstructor
|
|
| ArraySchemaConstructor
|
|
| ObjectSchemaConstructor;
|
|
|
|
export type TestOptionsMessage<Extra extends Record<string, any> = {}, R = any> =
|
|
| string
|
|
| ((params: Extra & Partial<TestMessageParams>) => R);
|
|
|
|
export interface Schema<T> {
|
|
clone(): this;
|
|
label(label: string): this;
|
|
meta(metadata: any): this;
|
|
meta(): any;
|
|
describe(): SchemaDescription;
|
|
concat(schema: this): this;
|
|
validate(value: any, options?: ValidateOptions): Promise<T>;
|
|
validateSync(value: any, options?: ValidateOptions): T;
|
|
validateAt(path: string, value: T, options?: ValidateOptions): Promise<T>;
|
|
validateSyncAt(path: string, value: T, options?: ValidateOptions): T;
|
|
isValid(value: any, options?: any): Promise<boolean>;
|
|
isValidSync(value: any, options?: any): value is T;
|
|
cast(value: any, options?: any): T;
|
|
isType(value: any): value is T;
|
|
strict(isStrict: boolean): this;
|
|
strip(strip: boolean): this;
|
|
withMutation(fn: (current: this) => void): void;
|
|
default(value: any): this;
|
|
default(): T;
|
|
typeError(message?: TestOptionsMessage): this;
|
|
oneOf(arrayOfValues: Array<T | Ref | null>, message?: MixedLocale['oneOf']): this;
|
|
notOneOf(arrayOfValues: any[], message?: MixedLocale['notOneOf']): this;
|
|
when(keys: string | any[], builder: WhenOptions<this>): this;
|
|
test(
|
|
name: string,
|
|
message: TestOptionsMessage,
|
|
test: (this: TestContext, value?: any) => boolean | ValidationError | Promise<boolean | ValidationError>,
|
|
callbackStyleAsync?: boolean,
|
|
): this;
|
|
// tslint:disable-next-line:no-unnecessary-generics
|
|
test<P>(options: TestOptions<P>): this;
|
|
transform(fn: TransformFunction<this>): this;
|
|
}
|
|
|
|
export interface MixedSchemaConstructor {
|
|
// tslint:disable-next-line:no-unnecessary-generics
|
|
<T = any>(): MixedSchema<T>;
|
|
// tslint:disable-next-line:no-unnecessary-generics
|
|
new <T = any>(options?: { type?: string; [key: string]: any }): MixedSchema<T>;
|
|
}
|
|
|
|
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>;
|
|
concat(schema: this): this;
|
|
concat<U>(schema: MixedSchema<U>): MixedSchema<T | U>;
|
|
}
|
|
|
|
export interface StringSchemaConstructor {
|
|
(): StringSchema;
|
|
new (): StringSchema;
|
|
}
|
|
|
|
export interface StringSchema<T extends string | null | undefined = string> extends Schema<T> {
|
|
length(limit: number | Ref, message?: StringLocale['length']): StringSchema<T>;
|
|
min(limit: number | Ref, message?: StringLocale['min']): StringSchema<T>;
|
|
max(limit: number | Ref, message?: StringLocale['max']): StringSchema<T>;
|
|
matches(
|
|
regex: RegExp,
|
|
messageOrOptions?:
|
|
| StringLocale['matches']
|
|
| { message?: StringLocale['matches']; excludeEmptyString?: boolean },
|
|
): StringSchema<T>;
|
|
email(message?: StringLocale['email']): StringSchema<T>;
|
|
url(message?: StringLocale['url']): StringSchema<T>;
|
|
ensure(): StringSchema<T>;
|
|
trim(message?: StringLocale['trim']): StringSchema<T>;
|
|
lowercase(message?: StringLocale['lowercase']): StringSchema<T>;
|
|
uppercase(message?: StringLocale['uppercase']): 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 {
|
|
(): NumberSchema;
|
|
new (): NumberSchema;
|
|
}
|
|
|
|
export interface NumberSchema<T extends number | null | undefined = number> extends Schema<T> {
|
|
min(limit: number | Ref, message?: NumberLocale['min']): NumberSchema<T>;
|
|
max(limit: number | Ref, message?: NumberLocale['max']): NumberSchema<T>;
|
|
lessThan(limit: number | Ref, message?: NumberLocale['lessThan']): NumberSchema<T>;
|
|
moreThan(limit: number | Ref, message?: NumberLocale['moreThan']): NumberSchema<T>;
|
|
positive(message?: NumberLocale['positive']): NumberSchema<T>;
|
|
negative(message?: NumberLocale['negative']): NumberSchema<T>;
|
|
integer(message?: NumberLocale['integer']): NumberSchema<T>;
|
|
truncate(): NumberSchema<T>;
|
|
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 {
|
|
(): BooleanSchema;
|
|
new (): BooleanSchema;
|
|
}
|
|
|
|
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 {
|
|
(): DateSchema;
|
|
new (): DateSchema;
|
|
}
|
|
|
|
export interface DateSchema<T extends Date | null | undefined = Date> extends Schema<T> {
|
|
min(limit: Date | string | Ref, message?: DateLocale['min']): DateSchema<T>;
|
|
max(limit: Date | string | Ref, message?: DateLocale['max']): 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 {
|
|
<T>(schema?: Schema<T>): ArraySchema<T>;
|
|
new (): ArraySchema<{}>;
|
|
}
|
|
|
|
interface BasicArraySchema<T extends any[] | null | undefined> extends Schema<T> {
|
|
min(limit: number | Ref, message?: ArrayLocale['min']): this;
|
|
max(limit: number | Ref, message?: ArrayLocale['max']): this;
|
|
ensure(): this;
|
|
compact(
|
|
rejector?: (value: InferredArrayType<T>, index: number, array: Array<InferredArrayType<T>>) => boolean,
|
|
): this;
|
|
}
|
|
|
|
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;
|
|
};
|
|
|
|
/**
|
|
* Merges two interfaces. For properties in common, property types from `U` trump those of `T`.
|
|
* 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 | null | undefined, U extends object> = {
|
|
[P in keyof T]: P extends keyof U ? U[P] : T[P];
|
|
} &
|
|
U;
|
|
|
|
export interface ObjectSchemaConstructor {
|
|
<T extends object>(fields?: ObjectSchemaDefinition<T>): ObjectSchema<T>;
|
|
new (): ObjectSchema<{}>;
|
|
}
|
|
|
|
export interface ObjectSchema<T extends object | null | undefined = object> extends Schema<T> {
|
|
shape<U extends object>(
|
|
fields: ObjectSchemaDefinition<U>,
|
|
noSortEdges?: Array<[string, string]>,
|
|
): ObjectSchema<Shape<T, U>>;
|
|
from(fromKey: string, toKey: string, alias?: boolean): ObjectSchema<T>;
|
|
noUnknown(onlyKnownKeys?: boolean, message?: ObjectLocale['noUnknown']): ObjectSchema<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>;
|
|
concat(schema: this): this;
|
|
concat<U extends object>(schema: ObjectSchema<U>): ObjectSchema<T & U>;
|
|
}
|
|
|
|
export type TransformFunction<T> = (this: T, value: any, originalValue: any) => any;
|
|
|
|
export interface WhenOptionsBuilderFunction<T> {
|
|
(value: any, schema: T): T;
|
|
(v1: any, v2: any, schema: T): T;
|
|
(v1: any, v2: any, v3: any, schema: T): T;
|
|
(v1: any, v2: any, v3: any, v4: any, schema: T): T;
|
|
}
|
|
|
|
export type WhenOptionsBuilderObjectIs = ((...values: any[]) => boolean) | boolean | number | null | object | string;
|
|
|
|
export type WhenOptionsBuilderObject =
|
|
| {
|
|
is: WhenOptionsBuilderObjectIs;
|
|
then: any;
|
|
otherwise: any;
|
|
}
|
|
| object;
|
|
|
|
export type WhenOptions<T> = WhenOptionsBuilderFunction<T> | WhenOptionsBuilderObject;
|
|
|
|
export interface TestContext {
|
|
path: string;
|
|
options: ValidateOptions;
|
|
parent: any;
|
|
schema: Schema<any>;
|
|
resolve: (value: any) => any;
|
|
createError: (params?: { path?: string; message?: string }) => ValidationError;
|
|
}
|
|
|
|
export interface ValidateOptions {
|
|
/**
|
|
* Only validate the input, and skip and coercion or transformation. Default - false
|
|
*/
|
|
strict?: boolean;
|
|
/**
|
|
* Teturn from validation methods on the first error rather than after all validations run. Default - true
|
|
*/
|
|
abortEarly?: boolean;
|
|
/**
|
|
* Remove unspecified keys from objects. Default - false
|
|
*/
|
|
stripUnknown?: boolean;
|
|
/**
|
|
* When false validations will not descend into nested schema (relevant for objects or arrays). Default - true
|
|
*/
|
|
recursive?: boolean;
|
|
/**
|
|
* Any context needed for validating schema conditions (see: when())
|
|
*/
|
|
context?: object;
|
|
}
|
|
|
|
export interface TestMessageParams {
|
|
path: string;
|
|
value: any;
|
|
originalValue: any;
|
|
label: string;
|
|
}
|
|
|
|
export interface TestOptions<P extends Record<string, any> = {}, R = any> {
|
|
/**
|
|
* Unique name identifying the test
|
|
*/
|
|
name?: string;
|
|
|
|
/**
|
|
* Test function, determines schema validity
|
|
*/
|
|
test: (this: TestContext, value: any) => boolean | ValidationError | Promise<boolean | ValidationError>;
|
|
|
|
/**
|
|
* The validation error message
|
|
*/
|
|
message?: TestOptionsMessage<P, R>;
|
|
|
|
/**
|
|
* Values passed to message for interpolation
|
|
*/
|
|
params?: P;
|
|
|
|
/**
|
|
* Mark the test as exclusive, meaning only one of the same can be active at once
|
|
*/
|
|
exclusive?: boolean;
|
|
}
|
|
|
|
export interface SchemaDescription {
|
|
type: string;
|
|
label: string;
|
|
meta: object;
|
|
tests: Array<{ name: string; params: object }>;
|
|
fields: object;
|
|
}
|
|
|
|
// ValidationError works a lot more like a class vs. a constructor
|
|
// function that returns an interface. It's also got a couple of
|
|
// static methods and it inherits from the generic Error class in
|
|
// the [yup codebase][1].
|
|
// [1]: (https://github.com/jquense/yup/blob/master/src/ValidationError.js)
|
|
export class ValidationError extends Error {
|
|
name: string;
|
|
message: string;
|
|
value: any;
|
|
/**
|
|
* A string, indicating where there error was thrown. path is empty at the root level.
|
|
*/
|
|
path: string;
|
|
type: any;
|
|
/**
|
|
* array of error messages
|
|
*/
|
|
errors: string[];
|
|
|
|
/**
|
|
* In the case of aggregate errors, inner is an array of ValidationErrors throw earlier in the validation chain.
|
|
*/
|
|
inner: ValidationError[];
|
|
params?: object;
|
|
|
|
static isError(err: any): err is ValidationError;
|
|
static formatError(message: string | ((params?: any) => string), params?: any): string | ((params?: any) => string);
|
|
|
|
constructor(errors: string | string[], value: any, path: string, type?: any);
|
|
}
|
|
|
|
// It is tempting to declare `Ref` very simply, but there are problems with these approaches:
|
|
//
|
|
// * `type Ref = Record<string, any>;` - This is essentially how it was originally declared, but
|
|
// just about any object satisfies this contract, which makes the type declaration too loose to
|
|
// be useful.
|
|
//
|
|
// * `type Ref = object;` - This is a variation on the previous bullet in that it is too loose.
|
|
//
|
|
// * `class Ref {}` - This is yet another variation that is too loose.
|
|
//
|
|
// * `type Ref = void;` - This works and the emitted JavaScript is just fine, but it results in some
|
|
// confusing IntelliSense, e.g it looks like the `ref()` returns `void`, which is not the case.
|
|
//
|
|
// The solution is twofold. 1.) Declare it as a class with a private constructor to prevent it from
|
|
// being instantiated by anything but the `ref()` factory function, and; 2.) declare a private
|
|
// readonly property (that yup actually places on the prototype) to force it to be structurally
|
|
// incompatible with any other object type.
|
|
|
|
/**
|
|
* `Ref` is an opaque type that is internal to yup. Creating a `Ref` instance is accomplished via the `ref()` factory
|
|
* function.
|
|
*/
|
|
export class Ref {
|
|
private constructor();
|
|
private readonly __isYupRef: true;
|
|
}
|
|
|
|
// tslint:disable-next-line:no-empty-interface
|
|
export interface Lazy extends Schema<any> {}
|
|
|
|
export interface FormatErrorParams {
|
|
path: string;
|
|
type: string;
|
|
value?: any;
|
|
originalValue?: any;
|
|
}
|
|
|
|
export type LocaleValue = string | ((params: FormatErrorParams) => string);
|
|
|
|
interface MixedLocale {
|
|
default?: TestOptionsMessage;
|
|
required?: TestOptionsMessage;
|
|
oneOf?: TestOptionsMessage<{ values: any }>;
|
|
notOneOf?: TestOptionsMessage<{ values: any }>;
|
|
notType?: LocaleValue;
|
|
}
|
|
|
|
interface StringLocale {
|
|
length?: TestOptionsMessage<{ length: number }>;
|
|
min?: TestOptionsMessage<{ min: number }>;
|
|
max?: TestOptionsMessage<{ max: number }>;
|
|
matches?: TestOptionsMessage<{ regex: RegExp }>;
|
|
email?: TestOptionsMessage<{ regex: RegExp }>;
|
|
url?: TestOptionsMessage<{ regex: RegExp }>;
|
|
trim?: TestOptionsMessage;
|
|
lowercase?: TestOptionsMessage;
|
|
uppercase?: TestOptionsMessage;
|
|
}
|
|
|
|
interface NumberLocale {
|
|
min?: TestOptionsMessage<{ min: number }>;
|
|
max?: TestOptionsMessage<{ max: number }>;
|
|
lessThan?: TestOptionsMessage<{ less: number }>;
|
|
moreThan?: TestOptionsMessage<{ more: number }>;
|
|
positive?: TestOptionsMessage<{ more: number }>;
|
|
negative?: TestOptionsMessage<{ less: number }>;
|
|
integer?: TestOptionsMessage;
|
|
}
|
|
|
|
interface DateLocale {
|
|
min?: TestOptionsMessage<{ min: Date | string }>;
|
|
max?: TestOptionsMessage<{ max: Date | string }>;
|
|
}
|
|
|
|
interface ObjectLocale {
|
|
noUnknown?: TestOptionsMessage;
|
|
}
|
|
|
|
interface ArrayLocale {
|
|
min?: TestOptionsMessage<{ min: number }>;
|
|
max?: TestOptionsMessage<{ max: number }>;
|
|
}
|
|
|
|
export interface LocaleObject {
|
|
mixed?: MixedLocale;
|
|
string?: StringLocale;
|
|
number?: NumberLocale;
|
|
date?: DateLocale;
|
|
boolean?: {};
|
|
object?: ObjectLocale;
|
|
array?: ArrayLocale;
|
|
}
|
|
|
|
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 Id<T> = { [K in keyof T]: T[K] };
|
|
type RequiredProps<T> = Pick<T, Exclude<keyof T, KeyOfUndefined<T>>>;
|
|
type NotRequiredProps<T> = Partial<Pick<T, KeyOfUndefined<T>>>;
|
|
type InnerInferType<T> = Id<NotRequiredProps<T> & RequiredProps<T>>;
|
|
type InferredArrayType<T> = T extends Array<infer U> ? U : T;
|