diff --git a/types/yup/index.d.ts b/types/yup/index.d.ts index b2b373f9ea..f8164ac816 100644 --- a/types/yup/index.d.ts +++ b/types/yup/index.d.ts @@ -13,7 +13,7 @@ // Maurice de Beijer // Kalley Powell // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 3.1 +// TypeScript Version: 2.8 export function reach(schema: Schema, path: string, value?: any, context?: any): Schema; export function addMethod>( @@ -69,8 +69,8 @@ export interface Schema { default(value: any): this; default(): T; typeError(message?: TestOptionsMessage): this; - oneOf(arrayOfValues: Array, message?: TestOptionsMessage<{ values: T | Ref }>): this; - notOneOf(arrayOfValues: any[], message?: TestOptionsMessage<{ values: T | Ref }>): this; + oneOf(arrayOfValues: Array, message?: MixedLocale['oneOf']): this; + notOneOf(arrayOfValues: any[], message?: MixedLocale['notOneOf']): this; when(keys: string | any[], builder: WhenOptions): this; test( name: string, @@ -106,21 +106,21 @@ export interface StringSchemaConstructor { } export interface StringSchema extends Schema { - length(limit: number | Ref, message?: TestOptionsMessage<{ length: number | Ref }>): StringSchema; - min(limit: number | Ref, message?: TestOptionsMessage<{ min: number | Ref }>): StringSchema; - max(limit: number | Ref, message?: TestOptionsMessage<{ max: number | Ref }>): StringSchema; + length(limit: number | Ref, message?: StringLocale['length']): StringSchema; + min(limit: number | Ref, message?: StringLocale['min']): StringSchema; + max(limit: number | Ref, message?: StringLocale['max']): StringSchema; matches( regex: RegExp, messageOrOptions?: - | TestOptionsMessage<{ regex: RegExp }> - | { message?: TestOptionsMessage<{ regex: RegExp }>; excludeEmptyString?: boolean }, + | StringLocale['matches'] + | { message?: StringLocale['matches']; excludeEmptyString?: boolean }, ): StringSchema; - email(message?: TestOptionsMessage<{ regex: RegExp }>): StringSchema; - url(message?: TestOptionsMessage<{ regex: RegExp }>): StringSchema; + email(message?: StringLocale['email']): StringSchema; + url(message?: StringLocale['url']): StringSchema; ensure(): StringSchema; - trim(message?: TestOptionsMessage): StringSchema; - lowercase(message?: TestOptionsMessage): StringSchema; - uppercase(message?: TestOptionsMessage): StringSchema; + trim(message?: StringLocale['trim']): StringSchema; + lowercase(message?: StringLocale['lowercase']): StringSchema; + uppercase(message?: StringLocale['uppercase']): StringSchema; nullable(isNullable?: true): StringSchema; nullable(isNullable: false): StringSchema>; nullable(isNullable?: boolean): StringSchema; @@ -134,13 +134,13 @@ export interface NumberSchemaConstructor { } export interface NumberSchema extends Schema { - min(limit: number | Ref, message?: TestOptionsMessage<{ min: number }>): NumberSchema; - max(limit: number | Ref, message?: TestOptionsMessage<{ max: number }>): NumberSchema; - lessThan(limit: number | Ref, message?: TestOptionsMessage<{ less: number }>): NumberSchema; - moreThan(limit: number | Ref, message?: TestOptionsMessage<{ more: number }>): NumberSchema; - positive(message?: TestOptionsMessage<{ more: number }>): NumberSchema; - negative(message?: TestOptionsMessage<{ less: number }>): NumberSchema; - integer(message?: TestOptionsMessage): NumberSchema; + min(limit: number | Ref, message?: NumberLocale['min']): NumberSchema; + max(limit: number | Ref, message?: NumberLocale['max']): NumberSchema; + lessThan(limit: number | Ref, message?: NumberLocale['lessThan']): NumberSchema; + moreThan(limit: number | Ref, message?: NumberLocale['moreThan']): NumberSchema; + positive(message?: NumberLocale['positive']): NumberSchema; + negative(message?: NumberLocale['negative']): NumberSchema; + integer(message?: NumberLocale['integer']): NumberSchema; truncate(): NumberSchema; round(type: 'floor' | 'ceil' | 'trunc' | 'round'): NumberSchema; nullable(isNullable?: true): NumberSchema; @@ -169,8 +169,8 @@ export interface DateSchemaConstructor { } export interface DateSchema extends Schema { - min(limit: Date | string | Ref, message?: TestOptionsMessage<{ min: Date | string }>): DateSchema; - max(limit: Date | string | Ref, message?: TestOptionsMessage<{ max: Date | string }>): DateSchema; + min(limit: Date | string | Ref, message?: DateLocale['min']): DateSchema; + max(limit: Date | string | Ref, message?: DateLocale['max']): DateSchema; nullable(isNullable?: true): DateSchema; nullable(isNullable: false): DateSchema>; nullable(isNullable?: boolean): DateSchema; @@ -184,8 +184,8 @@ export interface ArraySchemaConstructor { } interface BasicArraySchema extends Schema { - min(limit: number | Ref, message?: TestOptionsMessage<{ min: number }>): this; - max(limit: number | Ref, message?: TestOptionsMessage<{ max: number }>): this; + min(limit: number | Ref, message?: ArrayLocale['min']): this; + max(limit: number | Ref, message?: ArrayLocale['max']): this; ensure(): this; compact( rejector?: (value: InferredArrayType, index: number, array: Array>) => boolean, @@ -252,7 +252,7 @@ export interface ObjectSchema exte noSortEdges?: Array<[string, string]>, ): ObjectSchema>; from(fromKey: string, toKey: string, alias?: boolean): ObjectSchema; - noUnknown(onlyKnownKeys?: boolean, message?: TestOptionsMessage): ObjectSchema; + noUnknown(onlyKnownKeys?: boolean, message?: ObjectLocale['noUnknown']): ObjectSchema; transformKeys(callback: (key: any) => any): void; camelCase(): ObjectSchema; constantCase(): ObjectSchema; @@ -430,23 +430,58 @@ export interface FormatErrorParams { export type LocaleValue = string | ((params: FormatErrorParams) => string); -type MessageFromParameters

= { - [K in keyof P]: P[K] extends TestOptionsMessage ? P[K] : never; -}[number]; +interface MixedLocale { + default?: TestOptionsMessage; + required?: TestOptionsMessage; + oneOf?: TestOptionsMessage<{ values: any }>; + notOneOf?: TestOptionsMessage<{ values: any }>; + notType?: LocaleValue; +} -type MappedLocaleSchema> = { - [key in keyof S]?: S[key] extends (...args: infer P) => any ? MessageFromParameters> : never; -}; +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?: MappedLocaleSchema & { notType?: LocaleValue }; - string?: MappedLocaleSchema; - number?: MappedLocaleSchema; - boolean?: MappedLocaleSchema; - bool?: MappedLocaleSchema; - date?: MappedLocaleSchema; - array?: MappedLocaleSchema>; - object?: MappedLocaleSchema>; + mixed?: MixedLocale; + string?: StringLocale; + number?: NumberLocale; + date?: DateLocale; + boolean?: {}; + object?: ObjectLocale; + array?: ArrayLocale; } export type InferType = T extends Schema ? InnerInferType

: never; diff --git a/types/yup/yup-tests.ts b/types/yup/yup-tests.ts index a8d9c8ee0c..a8e2c99cc7 100644 --- a/types/yup/yup-tests.ts +++ b/types/yup/yup-tests.ts @@ -487,6 +487,51 @@ const localeNotType3: LocaleObject = { }, }, }; +// tslint:disable:no-invalid-template-strings +const exhaustiveLocalObjectconst: LocaleObject = { + mixed: { + default: '${path} is invalid', + required: '${path} is a required field', + oneOf: '${path} must be one of the following values: ${values}', + notOneOf: '${path} must not be one of the following values: ${values}', + notType: '${path} is not the correct type', + }, + string: { + length: '${path} must be exactly ${length} characters', + min: '${path} must be at least ${min} characters', + max: '${path} must be at most ${max} characters', + matches: '${path} must match the following: "${regex}"', + email: '${path} must be a valid email', + url: '${path} must be a valid URL', + trim: '${path} must be a trimmed string', + lowercase: '${path} must be a lowercase string', + uppercase: '${path} must be a upper case string', + }, + number: { + min: '${path} must be greater than or equal to ${min}', + max: '${path} must be less than or equal to ${max}', + lessThan: '${path} must be less than ${less}', + moreThan: '${path} must be greater than ${more}', + positive: '${path} must be a positive number', + negative: '${path} must be a negative number', + integer: '${path} must be an integer', + }, + date: { + min: '${path} field must be later than ${min}', + max: '${path} field must be at earlier than ${max}', + }, + boolean: { + // NOOP + }, + object: { + noUnknown: '${path} field cannot have keys not specified in the object shape', + }, + array: { + min: '${path} field must have at least ${min} items', + max: '${path} field must have less than or equal to ${max} items', + }, +}; +// tslint:enable:no-invalid-template-strings yup.setLocale({ mixed: { @@ -500,8 +545,8 @@ yup.setLocale({ }); yup.setLocale({ - // $ExpectError string: { + // $ExpectError nullable: 'message', }, });