From 60fe3b06f2dde6d1663d444e8eacafc61909b16e Mon Sep 17 00:00:00 2001 From: Jason Quense Date: Sat, 25 Feb 2023 10:52:39 -0800 Subject: [PATCH] Followups (#1924) * feat: expose default locale * fix(types): fix add method type not accepting valid schema * fix: revert when types to simpler, less accurate but functional types. * fix up types --- src/Condition.ts | 52 ++++++++++++++-------------------- src/index.ts | 6 ++-- src/schema.ts | 28 ++++-------------- test/types/types.ts | 69 +++++++++++++++++++++++++-------------------- 4 files changed, 70 insertions(+), 85 deletions(-) diff --git a/src/Condition.ts b/src/Condition.ts index 63692f6ff..6a3676d5e 100644 --- a/src/Condition.ts +++ b/src/Condition.ts @@ -2,19 +2,16 @@ import isSchema from './util/isSchema'; import Reference from './Reference'; import type { ISchema } from './types'; -export type ConditionBuilder< - T extends ISchema, - U extends ISchema = T, -> = (values: any[], schema: T, options: ResolveOptions) => U; - -export type ConditionConfig< - T extends ISchema, - TThen extends ISchema = T, - TOtherwise extends ISchema = T, -> = { +export type ConditionBuilder> = ( + values: any[], + schema: T, + options: ResolveOptions, +) => ISchema; + +export type ConditionConfig> = { is: any | ((...values: any[]) => boolean); - then?: (schema: T) => TThen; - otherwise?: (schema: T) => TOtherwise; + then?: (schema: T) => ISchema; + otherwise?: (schema: T) => ISchema; }; export type ResolveOptions = { @@ -23,17 +20,13 @@ export type ResolveOptions = { context?: TContext; }; -class Condition< - TIn extends ISchema = ISchema, - TOut extends ISchema = TIn, -> { - fn: ConditionBuilder; - - static fromOptions< - TIn extends ISchema, - TThen extends ISchema, - TOtherwise extends ISchema, - >(refs: Reference[], config: ConditionConfig) { +class Condition = ISchema> { + fn: ConditionBuilder; + + static fromOptions>( + refs: Reference[], + config: ConditionConfig, + ) { if (!config.then && !config.otherwise) throw new TypeError( 'either `then:` or `otherwise:` is required for `when()` conditions', @@ -46,19 +39,16 @@ class Condition< ? is : (...values: any[]) => values.every((value) => value === is); - return new Condition( - refs, - (values, schema: any) => { - let branch = check(...values) ? then : otherwise; + return new Condition(refs, (values, schema: any) => { + let branch = check(...values) ? then : otherwise; - return branch?.(schema) ?? schema; - }, - ); + return branch?.(schema) ?? schema; + }); } constructor( public refs: readonly Reference[], - builder: ConditionBuilder, + builder: ConditionBuilder, ) { this.refs = refs; this.fn = builder; diff --git a/src/index.ts b/src/index.ts index 8300d83d6..b6c0ef63c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,7 @@ import ValidationError from './ValidationError'; import reach, { getIn } from './util/reach'; import isSchema from './util/isSchema'; import setLocale, { LocaleObject } from './setLocale'; +import defaultLocale from './locale'; import Schema, { AnySchema, CastOptions as BaseCastOptions, @@ -28,12 +29,12 @@ import Schema, { } from './schema'; import type { InferType, ISchema, Message, ValidateOptions } from './types'; -function addMethod( +function addMethod>( schemaType: (...arg: any[]) => T, name: string, fn: (this: T, ...args: any[]) => T, ): void; -function addMethod AnySchema>( +function addMethod ISchema>( schemaType: T, name: string, fn: (this: InstanceType, ...args: any[]) => InstanceType, @@ -90,6 +91,7 @@ export { isSchema, addMethod, setLocale, + defaultLocale, ValidationError, }; diff --git a/src/schema.ts b/src/schema.ts index 1e30628c6..a1f46dcb3 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -763,29 +763,13 @@ export default abstract class Schema< return next; } - when = this>(builder: ConditionBuilder): U; - when = this>( - keys: string | string[], - builder: ConditionBuilder, - ): U; - when< - UThen extends ISchema = this, - UOtherwise extends ISchema = this, - >(options: ConditionConfig): UThen | UOtherwise; - when< - UThen extends ISchema = this, - UOtherwise extends ISchema = this, - >( - keys: string | string[], - options: ConditionConfig, - ): UThen | UOtherwise; + when(builder: ConditionBuilder): this; + when(keys: string | string[], builder: ConditionBuilder): this; + when(options: ConditionConfig): this; + when(keys: string | string[], options: ConditionConfig): this; when( - keys: - | string - | string[] - | ConditionBuilder - | ConditionConfig, - options?: ConditionBuilder | ConditionConfig, + keys: string | string[] | ConditionBuilder | ConditionConfig, + options?: ConditionBuilder | ConditionConfig, ) { if (!Array.isArray(keys) && typeof keys !== 'string') { options = keys; diff --git a/test/types/types.ts b/test/types/types.ts index 2949d4439..1bbf082f7 100644 --- a/test/types/types.ts +++ b/test/types/types.ts @@ -9,6 +9,7 @@ import { mixed, bool, reach, + addMethod, } from '../../src'; import { create as tuple } from '../../src/tuple'; import { create as lazy } from '../../src/Lazy'; @@ -969,36 +970,38 @@ Object: { } } -Conditions: { - // $ExpectType NumberSchema | StringSchema - string().when('foo', ([foo], schema) => (foo ? schema.required() : number())); - - // $ExpectType StringSchema - string().when('foo', ([foo], schema) => (foo ? schema.required() : schema)); - - // $ExpectType NumberSchema | StringSchema - string().when('foo', { - is: true, - then: () => number(), - otherwise: (s) => s.required(), - }); - - const result = object({ - foo: bool().defined(), - polyField: mixed().when('foo', { - is: true, - then: () => number(), - otherwise: (s) => s.required(), - }), - }).cast({ foo: true, polyField: '1' }); - - // $ExpectType { polyField?: string | number | undefined; foo: boolean; } - result; - - mixed() - .when('foo', ([foo]) => (foo ? string() : number())) - .min(1); -} +// Conditions: { +// // $ExpectType NumberSchema | StringSchema +// string().when('foo', ([foo], schema) => (foo ? schema.required() : number())); + +// // $ExpectType StringSchema +// string() +// .when('foo', ([foo], schema) => (foo ? schema.required() : schema)) +// .when('foo', ([foo], schema) => (foo ? schema.required() : schema)); + +// // $ExpectType NumberSchema | StringSchema +// string().when('foo', { +// is: true, +// then: () => number(), +// otherwise: (s) => s.required(), +// }); + +// const result = object({ +// foo: bool().defined(), +// polyField: mixed().when('foo', { +// is: true, +// then: () => number(), +// otherwise: (s) => s.required(), +// }), +// }).cast({ foo: true, polyField: '1' }); + +// // $ExpectType { polyField?: string | number | undefined; foo: boolean; } +// result; + +// mixed() +// .when('foo', ([foo]) => (foo ? string() : number())) +// .min(1); +// } TypeAssigning: { const _schema: ObjectSchema<{ @@ -1036,3 +1039,9 @@ reach: { // $ExpectType Reference<"foo"> | ISchema<"foo", AnyObject, any, any> const _3 = reach(obj, 'ref'); } + +addMethod: { + addMethod(string, 'foo', function () { + return this.clone(); + }); +}