|
1 | 1 | import isSchema from './util/isSchema';
|
2 |
| -import type { Callback, ValidateOptions } from './types'; |
| 2 | +import type { AnyObject, Callback, ValidateOptions } from './types'; |
3 | 3 | import type { ResolveOptions } from './Condition';
|
4 | 4 |
|
5 | 5 | import type {
|
6 |
| - AnySchema, |
7 | 6 | CastOptions,
|
8 |
| - ConfigOf, |
9 | 7 | SchemaFieldDescription,
|
10 | 8 | SchemaLazyDescription,
|
11 | 9 | } from './schema';
|
12 |
| -import { Config, TypedSchema, TypeOf } from './util/types'; |
13 |
| - |
14 |
| -export type LazyBuilder<T extends AnySchema = any> = ( |
| 10 | +import { Flags, ISchema } from './util/types'; |
| 11 | +import { BaseSchema } from '.'; |
| 12 | + |
| 13 | +export type LazyBuilder< |
| 14 | + T, |
| 15 | + TContext = AnyObject, |
| 16 | + TDefault = any, |
| 17 | + TFlags extends Flags = any, |
| 18 | +> = ( |
15 | 19 | value: any,
|
16 | 20 | options: ResolveOptions,
|
17 |
| -) => T; |
18 |
| - |
19 |
| -export function create<T extends AnySchema>(builder: LazyBuilder<T>) { |
20 |
| - return new Lazy(builder); |
| 21 | +) => ISchema<T, TContext, TFlags, TDefault>; |
| 22 | + |
| 23 | +export function create< |
| 24 | + T, |
| 25 | + TContext = AnyObject, |
| 26 | + TFlags extends Flags = any, |
| 27 | + TDefault = any, |
| 28 | +>(builder: LazyBuilder<T, TContext, TDefault, TFlags>) { |
| 29 | + return new Lazy<T, TContext, TDefault, TFlags>(builder); |
21 | 30 | }
|
22 | 31 |
|
23 |
| -export type LazyReturnValue<T> = T extends Lazy<infer TSchema> |
24 |
| - ? TSchema |
25 |
| - : never; |
26 |
| - |
27 |
| -export type LazyType<T> = LazyReturnValue<T> extends TypedSchema |
28 |
| - ? TypeOf<LazyReturnValue<T>> |
29 |
| - : never; |
30 |
| - |
31 | 32 | export interface LazySpec {
|
32 | 33 | meta: Record<string, unknown> | undefined;
|
33 | 34 | }
|
34 | 35 |
|
35 |
| -class Lazy<T extends AnySchema, TConfig extends Config = ConfigOf<T>> |
36 |
| - implements TypedSchema { |
| 36 | +class Lazy<T, TContext = AnyObject, TDefault = any, TFlags extends Flags = any> |
| 37 | + implements ISchema<T, TContext, TFlags, TDefault> |
| 38 | +{ |
37 | 39 | type = 'lazy' as const;
|
38 | 40 |
|
39 | 41 | __isYupSchema__ = true;
|
40 | 42 |
|
41 |
| - readonly __type!: T['__type']; |
42 |
| - readonly __outputType!: T['__outputType']; |
| 43 | + declare readonly __outputType: T; |
| 44 | + declare readonly __context: TContext; |
| 45 | + declare readonly __flags: TFlags; |
| 46 | + declare readonly __default: TDefault; |
43 | 47 |
|
44 | 48 | spec: LazySpec;
|
45 | 49 |
|
46 |
| - constructor(private builder: LazyBuilder<T>) { |
| 50 | + constructor(private builder: LazyBuilder<T, TContext, TDefault, TFlags>) { |
47 | 51 | this.spec = { meta: undefined };
|
48 | 52 | }
|
49 | 53 |
|
50 |
| - clone(): Lazy<T, TConfig> { |
51 |
| - const next = new Lazy(this.builder); |
| 54 | + clone(): Lazy<T, TContext, TDefault, TFlags> { |
| 55 | + const next = create(this.builder); |
52 | 56 | next.spec = { ...this.spec };
|
53 | 57 | return next;
|
54 | 58 | }
|
55 | 59 |
|
56 | 60 | private _resolve = (
|
57 | 61 | value: any,
|
58 |
| - options: ResolveOptions<TConfig['context']> = {}, |
59 |
| - ): T => { |
60 |
| - let schema = this.builder(value, options); |
| 62 | + options: ResolveOptions<TContext> = {}, |
| 63 | + ): BaseSchema<T, TContext, TDefault, TFlags> => { |
| 64 | + let schema = this.builder(value, options) as BaseSchema< |
| 65 | + T, |
| 66 | + TContext, |
| 67 | + TDefault, |
| 68 | + TFlags |
| 69 | + >; |
61 | 70 |
|
62 | 71 | if (!isSchema(schema))
|
63 | 72 | throw new TypeError('lazy() functions must return a valid schema');
|
64 | 73 |
|
65 | 74 | return schema.resolve(options);
|
66 | 75 | };
|
67 | 76 |
|
68 |
| - resolve(options: ResolveOptions<TConfig['context']>) { |
| 77 | + resolve(options: ResolveOptions<TContext>) { |
69 | 78 | return this._resolve(options.value, options);
|
70 | 79 | }
|
71 | 80 |
|
72 |
| - cast(value: any, options?: CastOptions<TConfig['context']>): T['__type'] { |
| 81 | + cast(value: any, options?: CastOptions<TContext>): T { |
73 | 82 | return this._resolve(value, options).cast(value, options);
|
74 | 83 | }
|
75 | 84 |
|
76 | 85 | validate(
|
77 | 86 | value: any,
|
78 | 87 | options?: ValidateOptions,
|
79 | 88 | maybeCb?: Callback,
|
80 |
| - ): T['__outputType'] { |
| 89 | + ): Promise<T> { |
81 | 90 | // @ts-expect-error missing public callback on type
|
82 | 91 | return this._resolve(value, options).validate(value, options, maybeCb);
|
83 | 92 | }
|
84 | 93 |
|
85 |
| - validateSync( |
86 |
| - value: any, |
87 |
| - options?: ValidateOptions<TConfig['context']>, |
88 |
| - ): T['__outputType'] { |
| 94 | + validateSync(value: any, options?: ValidateOptions<TContext>): T { |
89 | 95 | return this._resolve(value, options).validateSync(value, options);
|
90 | 96 | }
|
91 | 97 |
|
92 |
| - validateAt( |
93 |
| - path: string, |
94 |
| - value: any, |
95 |
| - options?: ValidateOptions<TConfig['context']>, |
96 |
| - ) { |
| 98 | + validateAt(path: string, value: any, options?: ValidateOptions<TContext>) { |
97 | 99 | return this._resolve(value, options).validateAt(path, value, options);
|
98 | 100 | }
|
99 | 101 |
|
100 | 102 | validateSyncAt(
|
101 | 103 | path: string,
|
102 | 104 | value: any,
|
103 |
| - options?: ValidateOptions<TConfig['context']>, |
| 105 | + options?: ValidateOptions<TContext>, |
104 | 106 | ) {
|
105 | 107 | return this._resolve(value, options).validateSyncAt(path, value, options);
|
106 | 108 | }
|
107 | 109 |
|
108 |
| - isValid(value: any, options?: ValidateOptions<TConfig['context']>) { |
| 110 | + isValid(value: any, options?: ValidateOptions<TContext>) { |
109 | 111 | return this._resolve(value, options).isValid(value, options);
|
110 | 112 | }
|
111 | 113 |
|
112 |
| - isValidSync(value: any, options?: ValidateOptions<TConfig['context']>) { |
| 114 | + isValidSync(value: any, options?: ValidateOptions<TContext>) { |
113 | 115 | return this._resolve(value, options).isValidSync(value, options);
|
114 | 116 | }
|
115 | 117 |
|
116 | 118 | describe(
|
117 |
| - options?: ResolveOptions<TConfig['context']>, |
| 119 | + options?: ResolveOptions<TContext>, |
118 | 120 | ): SchemaLazyDescription | SchemaFieldDescription {
|
119 | 121 | return options
|
120 | 122 | ? this.resolve(options).describe(options)
|
121 | 123 | : { type: 'lazy', meta: this.spec.meta, label: undefined };
|
122 | 124 | }
|
123 | 125 |
|
124 | 126 | meta(): Record<string, unknown> | undefined;
|
125 |
| - meta(obj: Record<string, unknown>): Lazy<T, TConfig>; |
| 127 | + meta(obj: Record<string, unknown>): Lazy<T, TContext, TDefault, TFlags>; |
126 | 128 | meta(...args: [Record<string, unknown>?]) {
|
127 | 129 | if (args.length === 0) return this.spec.meta;
|
128 | 130 |
|
|
0 commit comments