schematox 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/parse.js +8 -8
- package/dist/parse.js.map +1 -1
- package/package.json +3 -3
- package/src/tests/README.md +0 -390
- package/src/tests/by-struct/array.test.ts +0 -1684
- package/src/tests/by-struct/boolean.test.ts +0 -741
- package/src/tests/by-struct/literal.test.ts +0 -755
- package/src/tests/by-struct/number.test.ts +0 -1234
- package/src/tests/by-struct/object.test.ts +0 -1484
- package/src/tests/by-struct/record.test.ts +0 -1802
- package/src/tests/by-struct/string.test.ts +0 -1252
- package/src/tests/by-struct/tuple.test.ts +0 -1341
- package/src/tests/by-struct/union.test.ts +0 -1284
- package/src/tests/fixtures.ts +0 -53
- package/src/tests/fold-constants.ts +0 -247
- package/src/tests/fold-morph.ts +0 -49
- package/src/tests/type.ts +0 -1
- package/src/tests/types/extensions.test.ts +0 -117
- package/src/tests/types/infer.test.ts +0 -1413
- package/src/tests/utils.test.ts +0 -191
|
@@ -1,1684 +0,0 @@
|
|
|
1
|
-
import * as x from '../../'
|
|
2
|
-
import * as fixture from '../fixtures'
|
|
3
|
-
|
|
4
|
-
import type { StructSharedKeys } from '../type'
|
|
5
|
-
|
|
6
|
-
describe('Type inference and parse by schema/construct/struct (foldA)', () => {
|
|
7
|
-
it('required', () => {
|
|
8
|
-
const schema = {
|
|
9
|
-
type: 'array',
|
|
10
|
-
of: { type: 'boolean' },
|
|
11
|
-
} as const satisfies x.Schema
|
|
12
|
-
|
|
13
|
-
const struct = x.array(x.boolean())
|
|
14
|
-
|
|
15
|
-
type ExpectedSubj = boolean[]
|
|
16
|
-
|
|
17
|
-
const subjects: Array<ExpectedSubj> = [
|
|
18
|
-
[true, false],
|
|
19
|
-
[false, true],
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
foldA: {
|
|
23
|
-
const construct = x.makeStruct(schema)
|
|
24
|
-
|
|
25
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
26
|
-
|
|
27
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
28
|
-
|
|
29
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
30
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
31
|
-
|
|
32
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
33
|
-
|
|
34
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
35
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
36
|
-
|
|
37
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
38
|
-
|
|
39
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
40
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
41
|
-
|
|
42
|
-
type StandardSubj = NonNullable<
|
|
43
|
-
(typeof struct)['~standard']['types']
|
|
44
|
-
>['output']
|
|
45
|
-
|
|
46
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
47
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
48
|
-
|
|
49
|
-
/* parsed either type check */
|
|
50
|
-
|
|
51
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
52
|
-
|
|
53
|
-
const parsed = x.parse(schema, undefined)
|
|
54
|
-
|
|
55
|
-
type SchemaParsed = typeof parsed
|
|
56
|
-
|
|
57
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
58
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
59
|
-
|
|
60
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
61
|
-
|
|
62
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
63
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
64
|
-
|
|
65
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
66
|
-
|
|
67
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
68
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
69
|
-
|
|
70
|
-
type StandardParsed = Extract<
|
|
71
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
72
|
-
{ value: unknown }
|
|
73
|
-
>['value']
|
|
74
|
-
|
|
75
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
76
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
77
|
-
|
|
78
|
-
/* runtime schema check */
|
|
79
|
-
|
|
80
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
81
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
82
|
-
expect(construct.__schema === schema).toBe(false)
|
|
83
|
-
|
|
84
|
-
/* parse result check */
|
|
85
|
-
|
|
86
|
-
for (const subj of subjects) {
|
|
87
|
-
const schemaParsed = x.parse(schema, subj)
|
|
88
|
-
|
|
89
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
90
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
91
|
-
|
|
92
|
-
const constructParsed = construct.parse(subj)
|
|
93
|
-
|
|
94
|
-
expect(constructParsed.error).toBe(undefined)
|
|
95
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
96
|
-
|
|
97
|
-
const structParsed = struct.parse(subj)
|
|
98
|
-
|
|
99
|
-
expect(structParsed.error).toBe(undefined)
|
|
100
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
101
|
-
|
|
102
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
103
|
-
|
|
104
|
-
if (standardParsed instanceof Promise) {
|
|
105
|
-
throw Error('Not expected')
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (standardParsed.issues !== undefined) {
|
|
109
|
-
throw Error('not expected')
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('optional', () => {
|
|
118
|
-
const schema = {
|
|
119
|
-
type: 'array',
|
|
120
|
-
of: { type: 'boolean' },
|
|
121
|
-
optional: true,
|
|
122
|
-
} as const satisfies x.Schema
|
|
123
|
-
|
|
124
|
-
const struct = x.array(x.boolean()).optional()
|
|
125
|
-
|
|
126
|
-
type ExpectedSubj = boolean[] | undefined
|
|
127
|
-
|
|
128
|
-
const subjects: Array<ExpectedSubj> = [
|
|
129
|
-
[true, false],
|
|
130
|
-
[false, true],
|
|
131
|
-
undefined,
|
|
132
|
-
]
|
|
133
|
-
|
|
134
|
-
foldA: {
|
|
135
|
-
const construct = x.makeStruct(schema)
|
|
136
|
-
|
|
137
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
138
|
-
|
|
139
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
140
|
-
|
|
141
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
142
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
143
|
-
|
|
144
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
145
|
-
|
|
146
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
147
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
148
|
-
|
|
149
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
150
|
-
|
|
151
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
152
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
153
|
-
|
|
154
|
-
type StandardSubj = NonNullable<
|
|
155
|
-
(typeof struct)['~standard']['types']
|
|
156
|
-
>['output']
|
|
157
|
-
|
|
158
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
159
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
160
|
-
|
|
161
|
-
/* parsed either type check */
|
|
162
|
-
|
|
163
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
164
|
-
|
|
165
|
-
const parsed = x.parse(schema, undefined)
|
|
166
|
-
|
|
167
|
-
type SchemaParsed = typeof parsed
|
|
168
|
-
|
|
169
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
170
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
171
|
-
|
|
172
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
173
|
-
|
|
174
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
175
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
176
|
-
|
|
177
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
178
|
-
|
|
179
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
180
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
181
|
-
|
|
182
|
-
type StandardParsed = Extract<
|
|
183
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
184
|
-
{ value: unknown }
|
|
185
|
-
>['value']
|
|
186
|
-
|
|
187
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
188
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
189
|
-
|
|
190
|
-
/* runtime schema check */
|
|
191
|
-
|
|
192
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
193
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
194
|
-
expect(construct.__schema === schema).toBe(false)
|
|
195
|
-
|
|
196
|
-
/* parse result check */
|
|
197
|
-
|
|
198
|
-
for (const subj of subjects) {
|
|
199
|
-
const schemaParsed = x.parse(schema, subj)
|
|
200
|
-
|
|
201
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
202
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
203
|
-
|
|
204
|
-
const constructParsed = construct.parse(subj)
|
|
205
|
-
|
|
206
|
-
expect(constructParsed.error).toBe(undefined)
|
|
207
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
208
|
-
|
|
209
|
-
const structParsed = struct.parse(subj)
|
|
210
|
-
|
|
211
|
-
expect(structParsed.error).toBe(undefined)
|
|
212
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
213
|
-
|
|
214
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
215
|
-
|
|
216
|
-
if (standardParsed instanceof Promise) {
|
|
217
|
-
throw Error('Not expected')
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (standardParsed.issues !== undefined) {
|
|
221
|
-
throw Error('not expected')
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
it('nullable', () => {
|
|
230
|
-
const schema = {
|
|
231
|
-
type: 'array',
|
|
232
|
-
of: { type: 'boolean' },
|
|
233
|
-
nullable: true,
|
|
234
|
-
} as const satisfies x.Schema
|
|
235
|
-
|
|
236
|
-
const struct = x.array(x.boolean()).nullable()
|
|
237
|
-
|
|
238
|
-
type ExpectedSubj = boolean[] | null
|
|
239
|
-
|
|
240
|
-
const subjects: Array<ExpectedSubj> = [[true, false], [false, true], null]
|
|
241
|
-
|
|
242
|
-
foldA: {
|
|
243
|
-
const construct = x.makeStruct(schema)
|
|
244
|
-
|
|
245
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
246
|
-
|
|
247
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
248
|
-
|
|
249
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
250
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
251
|
-
|
|
252
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
253
|
-
|
|
254
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
255
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
256
|
-
|
|
257
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
258
|
-
|
|
259
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
260
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
261
|
-
|
|
262
|
-
type StandardSubj = NonNullable<
|
|
263
|
-
(typeof struct)['~standard']['types']
|
|
264
|
-
>['output']
|
|
265
|
-
|
|
266
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
267
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
268
|
-
|
|
269
|
-
/* parsed either type check */
|
|
270
|
-
|
|
271
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
272
|
-
|
|
273
|
-
const parsed = x.parse(schema, undefined)
|
|
274
|
-
|
|
275
|
-
type SchemaParsed = typeof parsed
|
|
276
|
-
|
|
277
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
278
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
279
|
-
|
|
280
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
281
|
-
|
|
282
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
283
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
284
|
-
|
|
285
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
286
|
-
|
|
287
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
288
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
289
|
-
|
|
290
|
-
type StandardParsed = Extract<
|
|
291
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
292
|
-
{ value: unknown }
|
|
293
|
-
>['value']
|
|
294
|
-
|
|
295
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
296
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
297
|
-
|
|
298
|
-
/* runtime schema check */
|
|
299
|
-
|
|
300
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
301
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
302
|
-
expect(construct.__schema === schema).toBe(false)
|
|
303
|
-
|
|
304
|
-
/* parse result check */
|
|
305
|
-
|
|
306
|
-
for (const subj of subjects) {
|
|
307
|
-
const schemaParsed = x.parse(schema, subj)
|
|
308
|
-
|
|
309
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
310
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
311
|
-
|
|
312
|
-
const constructParsed = construct.parse(subj)
|
|
313
|
-
|
|
314
|
-
expect(constructParsed.error).toBe(undefined)
|
|
315
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
316
|
-
|
|
317
|
-
const structParsed = struct.parse(subj)
|
|
318
|
-
|
|
319
|
-
expect(structParsed.error).toBe(undefined)
|
|
320
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
321
|
-
|
|
322
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
323
|
-
|
|
324
|
-
if (standardParsed instanceof Promise) {
|
|
325
|
-
throw Error('Not expected')
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (standardParsed.issues !== undefined) {
|
|
329
|
-
throw Error('not expected')
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
it('minLength', () => {
|
|
338
|
-
const schema = {
|
|
339
|
-
type: 'array',
|
|
340
|
-
of: { type: 'boolean' },
|
|
341
|
-
minLength: 2,
|
|
342
|
-
} as const satisfies x.Schema
|
|
343
|
-
|
|
344
|
-
const struct = x.array(x.boolean()).minLength(schema.minLength)
|
|
345
|
-
|
|
346
|
-
type ExpectedSubj = boolean[]
|
|
347
|
-
|
|
348
|
-
const subjects: Array<ExpectedSubj> = [
|
|
349
|
-
[true, false],
|
|
350
|
-
[false, true],
|
|
351
|
-
]
|
|
352
|
-
|
|
353
|
-
foldA: {
|
|
354
|
-
const construct = x.makeStruct(schema)
|
|
355
|
-
|
|
356
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
357
|
-
|
|
358
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
359
|
-
|
|
360
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
361
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
362
|
-
|
|
363
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
364
|
-
|
|
365
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
366
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
367
|
-
|
|
368
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
369
|
-
|
|
370
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
371
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
372
|
-
|
|
373
|
-
type StandardSubj = NonNullable<
|
|
374
|
-
(typeof struct)['~standard']['types']
|
|
375
|
-
>['output']
|
|
376
|
-
|
|
377
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
378
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
379
|
-
|
|
380
|
-
/* parsed either type check */
|
|
381
|
-
|
|
382
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
383
|
-
|
|
384
|
-
const parsed = x.parse(schema, undefined)
|
|
385
|
-
|
|
386
|
-
type SchemaParsed = typeof parsed
|
|
387
|
-
|
|
388
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
389
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
390
|
-
|
|
391
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
392
|
-
|
|
393
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
394
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
395
|
-
|
|
396
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
397
|
-
|
|
398
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
399
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
400
|
-
|
|
401
|
-
type StandardParsed = Extract<
|
|
402
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
403
|
-
{ value: unknown }
|
|
404
|
-
>['value']
|
|
405
|
-
|
|
406
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
407
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
408
|
-
|
|
409
|
-
/* runtime schema check */
|
|
410
|
-
|
|
411
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
412
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
413
|
-
expect(construct.__schema === schema).toBe(false)
|
|
414
|
-
|
|
415
|
-
/* parse result check */
|
|
416
|
-
|
|
417
|
-
for (const subj of subjects) {
|
|
418
|
-
const schemaParsed = x.parse(schema, subj)
|
|
419
|
-
|
|
420
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
421
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
422
|
-
|
|
423
|
-
const constructParsed = construct.parse(subj)
|
|
424
|
-
|
|
425
|
-
expect(constructParsed.error).toBe(undefined)
|
|
426
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
427
|
-
|
|
428
|
-
const structParsed = struct.parse(subj)
|
|
429
|
-
|
|
430
|
-
expect(structParsed.error).toBe(undefined)
|
|
431
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
432
|
-
|
|
433
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
434
|
-
|
|
435
|
-
if (standardParsed instanceof Promise) {
|
|
436
|
-
throw Error('Not expected')
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
if (standardParsed.issues !== undefined) {
|
|
440
|
-
throw Error('not expected')
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
it('maxLength', () => {
|
|
449
|
-
const schema = {
|
|
450
|
-
type: 'array',
|
|
451
|
-
of: { type: 'boolean' },
|
|
452
|
-
maxLength: 2,
|
|
453
|
-
} as const satisfies x.Schema
|
|
454
|
-
|
|
455
|
-
const struct = x.array(x.boolean()).maxLength(schema.maxLength)
|
|
456
|
-
|
|
457
|
-
type ExpectedSubj = boolean[]
|
|
458
|
-
|
|
459
|
-
const subjects: Array<ExpectedSubj> = [
|
|
460
|
-
[true, false],
|
|
461
|
-
[false, true],
|
|
462
|
-
]
|
|
463
|
-
|
|
464
|
-
foldA: {
|
|
465
|
-
const construct = x.makeStruct(schema)
|
|
466
|
-
|
|
467
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
468
|
-
|
|
469
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
470
|
-
|
|
471
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
472
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
473
|
-
|
|
474
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
475
|
-
|
|
476
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
477
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
478
|
-
|
|
479
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
480
|
-
|
|
481
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
482
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
483
|
-
|
|
484
|
-
type StandardSubj = NonNullable<
|
|
485
|
-
(typeof struct)['~standard']['types']
|
|
486
|
-
>['output']
|
|
487
|
-
|
|
488
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
489
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
490
|
-
|
|
491
|
-
/* parsed either type check */
|
|
492
|
-
|
|
493
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
494
|
-
|
|
495
|
-
const parsed = x.parse(schema, undefined)
|
|
496
|
-
|
|
497
|
-
type SchemaParsed = typeof parsed
|
|
498
|
-
|
|
499
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
500
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
501
|
-
|
|
502
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
503
|
-
|
|
504
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
505
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
506
|
-
|
|
507
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
508
|
-
|
|
509
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
510
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
511
|
-
|
|
512
|
-
type StandardParsed = Extract<
|
|
513
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
514
|
-
{ value: unknown }
|
|
515
|
-
>['value']
|
|
516
|
-
|
|
517
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
518
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
519
|
-
|
|
520
|
-
/* runtime schema check */
|
|
521
|
-
|
|
522
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
523
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
524
|
-
expect(construct.__schema === schema).toBe(false)
|
|
525
|
-
|
|
526
|
-
/* parse result check */
|
|
527
|
-
|
|
528
|
-
for (const subj of subjects) {
|
|
529
|
-
const schemaParsed = x.parse(schema, subj)
|
|
530
|
-
|
|
531
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
532
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
533
|
-
|
|
534
|
-
const constructParsed = construct.parse(subj)
|
|
535
|
-
|
|
536
|
-
expect(constructParsed.error).toBe(undefined)
|
|
537
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
538
|
-
|
|
539
|
-
const structParsed = struct.parse(subj)
|
|
540
|
-
|
|
541
|
-
expect(structParsed.error).toBe(undefined)
|
|
542
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
543
|
-
|
|
544
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
545
|
-
|
|
546
|
-
if (standardParsed instanceof Promise) {
|
|
547
|
-
throw Error('Not expected')
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (standardParsed.issues !== undefined) {
|
|
551
|
-
throw Error('not expected')
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
})
|
|
558
|
-
|
|
559
|
-
it('optional + nullable + minLength + maxLength', () => {
|
|
560
|
-
const schema = {
|
|
561
|
-
type: 'array',
|
|
562
|
-
of: { type: 'boolean' },
|
|
563
|
-
minLength: 2,
|
|
564
|
-
maxLength: 2,
|
|
565
|
-
optional: true,
|
|
566
|
-
nullable: true,
|
|
567
|
-
} as const satisfies x.Schema
|
|
568
|
-
|
|
569
|
-
const struct = x
|
|
570
|
-
.array(x.boolean())
|
|
571
|
-
.minLength(schema.minLength)
|
|
572
|
-
.maxLength(schema.maxLength)
|
|
573
|
-
.optional()
|
|
574
|
-
.nullable()
|
|
575
|
-
|
|
576
|
-
type ExpectedSubj = boolean[] | undefined | null
|
|
577
|
-
|
|
578
|
-
const subjects: Array<ExpectedSubj> = [
|
|
579
|
-
[true, false],
|
|
580
|
-
[false, true],
|
|
581
|
-
undefined,
|
|
582
|
-
null,
|
|
583
|
-
]
|
|
584
|
-
|
|
585
|
-
foldA: {
|
|
586
|
-
const construct = x.makeStruct(schema)
|
|
587
|
-
|
|
588
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
589
|
-
|
|
590
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
591
|
-
|
|
592
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
593
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
594
|
-
|
|
595
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
596
|
-
|
|
597
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
598
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
599
|
-
|
|
600
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
601
|
-
|
|
602
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
603
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
604
|
-
|
|
605
|
-
type StandardSubj = NonNullable<
|
|
606
|
-
(typeof struct)['~standard']['types']
|
|
607
|
-
>['output']
|
|
608
|
-
|
|
609
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
610
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
611
|
-
|
|
612
|
-
/* parsed either type check */
|
|
613
|
-
|
|
614
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
615
|
-
|
|
616
|
-
const parsed = x.parse(schema, undefined)
|
|
617
|
-
|
|
618
|
-
type SchemaParsed = typeof parsed
|
|
619
|
-
|
|
620
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
621
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
622
|
-
|
|
623
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
624
|
-
|
|
625
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
626
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
627
|
-
|
|
628
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
629
|
-
|
|
630
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
631
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
632
|
-
|
|
633
|
-
type StandardParsed = Extract<
|
|
634
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
635
|
-
{ value: unknown }
|
|
636
|
-
>['value']
|
|
637
|
-
|
|
638
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
639
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
640
|
-
|
|
641
|
-
/* runtime schema check */
|
|
642
|
-
|
|
643
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
644
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
645
|
-
expect(construct.__schema === schema).toBe(false)
|
|
646
|
-
|
|
647
|
-
/* parse result check */
|
|
648
|
-
|
|
649
|
-
for (const subj of subjects) {
|
|
650
|
-
const schemaParsed = x.parse(schema, subj)
|
|
651
|
-
|
|
652
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
653
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
654
|
-
|
|
655
|
-
const constructParsed = construct.parse(subj)
|
|
656
|
-
|
|
657
|
-
expect(constructParsed.error).toBe(undefined)
|
|
658
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
659
|
-
|
|
660
|
-
const structParsed = struct.parse(subj)
|
|
661
|
-
|
|
662
|
-
expect(structParsed.error).toBe(undefined)
|
|
663
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
664
|
-
|
|
665
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
666
|
-
|
|
667
|
-
if (standardParsed instanceof Promise) {
|
|
668
|
-
throw Error('Not expected')
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
if (standardParsed.issues !== undefined) {
|
|
672
|
-
throw Error('not expected')
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
})
|
|
679
|
-
})
|
|
680
|
-
|
|
681
|
-
describe('Struct parameter keys reduction and schema immutability (foldB)', () => {
|
|
682
|
-
it('optional', () => {
|
|
683
|
-
const schema = {
|
|
684
|
-
type: 'array',
|
|
685
|
-
of: { type: 'boolean' },
|
|
686
|
-
optional: true,
|
|
687
|
-
} as const satisfies x.Schema
|
|
688
|
-
|
|
689
|
-
const prevStruct = x.array(x.boolean())
|
|
690
|
-
const struct = prevStruct.optional()
|
|
691
|
-
|
|
692
|
-
type ExpectedKeys =
|
|
693
|
-
| StructSharedKeys
|
|
694
|
-
| 'description'
|
|
695
|
-
| 'maxLength'
|
|
696
|
-
| 'minLength'
|
|
697
|
-
| 'nullable'
|
|
698
|
-
|
|
699
|
-
foldB: {
|
|
700
|
-
const construct = x.makeStruct(schema)
|
|
701
|
-
|
|
702
|
-
/* ensure that struct keys are reduced after application */
|
|
703
|
-
|
|
704
|
-
type StructKeys = keyof typeof struct
|
|
705
|
-
|
|
706
|
-
x.tCh<StructKeys, ExpectedKeys>()
|
|
707
|
-
x.tCh<ExpectedKeys, StructKeys>()
|
|
708
|
-
|
|
709
|
-
type ConstructKeys = keyof typeof construct
|
|
710
|
-
|
|
711
|
-
x.tCh<ConstructKeys, ExpectedKeys>()
|
|
712
|
-
x.tCh<ExpectedKeys, ConstructKeys>()
|
|
713
|
-
|
|
714
|
-
/* ensure that construct/struct schema types are identical */
|
|
715
|
-
|
|
716
|
-
type ExpectedSchema = typeof schema
|
|
717
|
-
type StructSchema = typeof struct.__schema
|
|
718
|
-
|
|
719
|
-
x.tCh<StructSchema, ExpectedSchema>()
|
|
720
|
-
x.tCh<ExpectedSchema, StructSchema>()
|
|
721
|
-
|
|
722
|
-
type ConstructSchema = typeof struct.__schema
|
|
723
|
-
|
|
724
|
-
x.tCh<ConstructSchema, ExpectedSchema>()
|
|
725
|
-
x.tCh<ExpectedSchema, ConstructSchema>()
|
|
726
|
-
|
|
727
|
-
/* runtime schema check */
|
|
728
|
-
|
|
729
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
730
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
731
|
-
expect(construct.__schema === schema).toBe(false)
|
|
732
|
-
|
|
733
|
-
/* runtime schema parameter application immutability check */
|
|
734
|
-
|
|
735
|
-
expect(prevStruct.__schema === struct.__schema).toBe(false)
|
|
736
|
-
}
|
|
737
|
-
})
|
|
738
|
-
|
|
739
|
-
it('optional + nullable', () => {
|
|
740
|
-
const schema = {
|
|
741
|
-
type: 'array',
|
|
742
|
-
of: { type: 'boolean' },
|
|
743
|
-
optional: true,
|
|
744
|
-
nullable: true,
|
|
745
|
-
} as const satisfies x.Schema
|
|
746
|
-
|
|
747
|
-
const prevStruct = x.array(x.boolean()).optional()
|
|
748
|
-
const struct = prevStruct.nullable()
|
|
749
|
-
|
|
750
|
-
type ExpectedKeys =
|
|
751
|
-
| StructSharedKeys
|
|
752
|
-
| 'description'
|
|
753
|
-
| 'maxLength'
|
|
754
|
-
| 'minLength'
|
|
755
|
-
|
|
756
|
-
foldB: {
|
|
757
|
-
const construct = x.makeStruct(schema)
|
|
758
|
-
|
|
759
|
-
/* ensure that struct keys are reduced after application */
|
|
760
|
-
|
|
761
|
-
type StructKeys = keyof typeof struct
|
|
762
|
-
|
|
763
|
-
x.tCh<StructKeys, ExpectedKeys>()
|
|
764
|
-
x.tCh<ExpectedKeys, StructKeys>()
|
|
765
|
-
|
|
766
|
-
type ConstructKeys = keyof typeof construct
|
|
767
|
-
|
|
768
|
-
x.tCh<ConstructKeys, ExpectedKeys>()
|
|
769
|
-
x.tCh<ExpectedKeys, ConstructKeys>()
|
|
770
|
-
|
|
771
|
-
/* ensure that construct/struct schema types are identical */
|
|
772
|
-
|
|
773
|
-
type ExpectedSchema = typeof schema
|
|
774
|
-
type StructSchema = typeof struct.__schema
|
|
775
|
-
|
|
776
|
-
x.tCh<StructSchema, ExpectedSchema>()
|
|
777
|
-
x.tCh<ExpectedSchema, StructSchema>()
|
|
778
|
-
|
|
779
|
-
type ConstructSchema = typeof struct.__schema
|
|
780
|
-
|
|
781
|
-
x.tCh<ConstructSchema, ExpectedSchema>()
|
|
782
|
-
x.tCh<ExpectedSchema, ConstructSchema>()
|
|
783
|
-
|
|
784
|
-
/* runtime schema check */
|
|
785
|
-
|
|
786
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
787
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
788
|
-
expect(construct.__schema === schema).toBe(false)
|
|
789
|
-
|
|
790
|
-
/* runtime schema parameter application immutability check */
|
|
791
|
-
|
|
792
|
-
expect(prevStruct.__schema === struct.__schema).toBe(false)
|
|
793
|
-
}
|
|
794
|
-
})
|
|
795
|
-
|
|
796
|
-
it('optional + nullable + minLength', () => {
|
|
797
|
-
const schema = {
|
|
798
|
-
type: 'array',
|
|
799
|
-
of: { type: 'boolean' },
|
|
800
|
-
optional: true,
|
|
801
|
-
nullable: true,
|
|
802
|
-
minLength: 2,
|
|
803
|
-
} as const satisfies x.Schema
|
|
804
|
-
|
|
805
|
-
const prevStruct = x.array(x.boolean()).optional().nullable()
|
|
806
|
-
const struct = prevStruct.minLength(schema.minLength)
|
|
807
|
-
|
|
808
|
-
type ExpectedKeys = StructSharedKeys | 'description' | 'maxLength'
|
|
809
|
-
|
|
810
|
-
foldB: {
|
|
811
|
-
const construct = x.makeStruct(schema)
|
|
812
|
-
|
|
813
|
-
/* ensure that struct keys are reduced after application */
|
|
814
|
-
|
|
815
|
-
type StructKeys = keyof typeof struct
|
|
816
|
-
|
|
817
|
-
x.tCh<StructKeys, ExpectedKeys>()
|
|
818
|
-
x.tCh<ExpectedKeys, StructKeys>()
|
|
819
|
-
|
|
820
|
-
type ConstructKeys = keyof typeof construct
|
|
821
|
-
|
|
822
|
-
x.tCh<ConstructKeys, ExpectedKeys>()
|
|
823
|
-
x.tCh<ExpectedKeys, ConstructKeys>()
|
|
824
|
-
|
|
825
|
-
/* ensure that construct/struct schema types are identical */
|
|
826
|
-
|
|
827
|
-
type ExpectedSchema = typeof schema
|
|
828
|
-
type StructSchema = typeof struct.__schema
|
|
829
|
-
|
|
830
|
-
x.tCh<StructSchema, ExpectedSchema>()
|
|
831
|
-
x.tCh<ExpectedSchema, StructSchema>()
|
|
832
|
-
|
|
833
|
-
type ConstructSchema = typeof struct.__schema
|
|
834
|
-
|
|
835
|
-
x.tCh<ConstructSchema, ExpectedSchema>()
|
|
836
|
-
x.tCh<ExpectedSchema, ConstructSchema>()
|
|
837
|
-
|
|
838
|
-
/* runtime schema check */
|
|
839
|
-
|
|
840
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
841
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
842
|
-
expect(construct.__schema === schema).toBe(false)
|
|
843
|
-
|
|
844
|
-
/* runtime schema parameter application immutability check */
|
|
845
|
-
|
|
846
|
-
expect(prevStruct.__schema === struct.__schema).toBe(false)
|
|
847
|
-
}
|
|
848
|
-
})
|
|
849
|
-
|
|
850
|
-
it('optional + nullable + minLength + maxLength', () => {
|
|
851
|
-
const schema = {
|
|
852
|
-
type: 'array',
|
|
853
|
-
of: { type: 'boolean' },
|
|
854
|
-
optional: true,
|
|
855
|
-
nullable: true,
|
|
856
|
-
minLength: 2,
|
|
857
|
-
maxLength: 2,
|
|
858
|
-
} as const satisfies x.Schema
|
|
859
|
-
|
|
860
|
-
const prevStruct = x
|
|
861
|
-
.array(x.boolean())
|
|
862
|
-
.optional()
|
|
863
|
-
.nullable()
|
|
864
|
-
.minLength(schema.minLength)
|
|
865
|
-
|
|
866
|
-
const struct = prevStruct.maxLength(schema.maxLength)
|
|
867
|
-
|
|
868
|
-
type ExpectedKeys = StructSharedKeys | 'description'
|
|
869
|
-
|
|
870
|
-
foldB: {
|
|
871
|
-
const construct = x.makeStruct(schema)
|
|
872
|
-
|
|
873
|
-
/* ensure that struct keys are reduced after application */
|
|
874
|
-
|
|
875
|
-
type StructKeys = keyof typeof struct
|
|
876
|
-
|
|
877
|
-
x.tCh<StructKeys, ExpectedKeys>()
|
|
878
|
-
x.tCh<ExpectedKeys, StructKeys>()
|
|
879
|
-
|
|
880
|
-
type ConstructKeys = keyof typeof construct
|
|
881
|
-
|
|
882
|
-
x.tCh<ConstructKeys, ExpectedKeys>()
|
|
883
|
-
x.tCh<ExpectedKeys, ConstructKeys>()
|
|
884
|
-
|
|
885
|
-
/* ensure that construct/struct schema types are identical */
|
|
886
|
-
|
|
887
|
-
type ExpectedSchema = typeof schema
|
|
888
|
-
type StructSchema = typeof struct.__schema
|
|
889
|
-
|
|
890
|
-
x.tCh<StructSchema, ExpectedSchema>()
|
|
891
|
-
x.tCh<ExpectedSchema, StructSchema>()
|
|
892
|
-
|
|
893
|
-
type ConstructSchema = typeof struct.__schema
|
|
894
|
-
|
|
895
|
-
x.tCh<ConstructSchema, ExpectedSchema>()
|
|
896
|
-
x.tCh<ExpectedSchema, ConstructSchema>()
|
|
897
|
-
|
|
898
|
-
/* runtime schema check */
|
|
899
|
-
|
|
900
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
901
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
902
|
-
expect(construct.__schema === schema).toBe(false)
|
|
903
|
-
|
|
904
|
-
/* runtime schema parameter application immutability check */
|
|
905
|
-
|
|
906
|
-
expect(prevStruct.__schema === struct.__schema).toBe(false)
|
|
907
|
-
}
|
|
908
|
-
})
|
|
909
|
-
|
|
910
|
-
it('optional + nullable + minLength + maxLength + description', () => {
|
|
911
|
-
const schema = {
|
|
912
|
-
type: 'array',
|
|
913
|
-
of: { type: 'boolean' },
|
|
914
|
-
optional: true,
|
|
915
|
-
nullable: true,
|
|
916
|
-
minLength: 2,
|
|
917
|
-
maxLength: 2,
|
|
918
|
-
description: 'x',
|
|
919
|
-
} as const satisfies x.Schema
|
|
920
|
-
|
|
921
|
-
const prevStruct = x
|
|
922
|
-
.array(x.boolean())
|
|
923
|
-
.optional()
|
|
924
|
-
.nullable()
|
|
925
|
-
.minLength(schema.minLength)
|
|
926
|
-
.maxLength(schema.maxLength)
|
|
927
|
-
|
|
928
|
-
const struct = prevStruct.description(schema.description)
|
|
929
|
-
|
|
930
|
-
type ExpectedKeys = StructSharedKeys
|
|
931
|
-
|
|
932
|
-
foldB: {
|
|
933
|
-
const construct = x.makeStruct(schema)
|
|
934
|
-
|
|
935
|
-
/* ensure that struct keys are reduced after application */
|
|
936
|
-
|
|
937
|
-
type StructKeys = keyof typeof struct
|
|
938
|
-
|
|
939
|
-
x.tCh<StructKeys, ExpectedKeys>()
|
|
940
|
-
x.tCh<ExpectedKeys, StructKeys>()
|
|
941
|
-
|
|
942
|
-
type ConstructKeys = keyof typeof construct
|
|
943
|
-
|
|
944
|
-
x.tCh<ConstructKeys, ExpectedKeys>()
|
|
945
|
-
x.tCh<ExpectedKeys, ConstructKeys>()
|
|
946
|
-
|
|
947
|
-
/* ensure that construct/struct schema types are identical */
|
|
948
|
-
|
|
949
|
-
type ExpectedSchema = typeof schema
|
|
950
|
-
type StructSchema = typeof struct.__schema
|
|
951
|
-
|
|
952
|
-
x.tCh<StructSchema, ExpectedSchema>()
|
|
953
|
-
x.tCh<ExpectedSchema, StructSchema>()
|
|
954
|
-
|
|
955
|
-
type ConstructSchema = typeof struct.__schema
|
|
956
|
-
|
|
957
|
-
x.tCh<ConstructSchema, ExpectedSchema>()
|
|
958
|
-
x.tCh<ExpectedSchema, ConstructSchema>()
|
|
959
|
-
|
|
960
|
-
/* runtime schema check */
|
|
961
|
-
|
|
962
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
963
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
964
|
-
expect(construct.__schema === schema).toBe(false)
|
|
965
|
-
|
|
966
|
-
/* runtime schema parameter application immutability check */
|
|
967
|
-
|
|
968
|
-
expect(prevStruct.__schema === struct.__schema).toBe(false)
|
|
969
|
-
}
|
|
970
|
-
})
|
|
971
|
-
|
|
972
|
-
it('description + maxLength + minLength + nullable + optional', () => {
|
|
973
|
-
const schema = {
|
|
974
|
-
type: 'array',
|
|
975
|
-
of: { type: 'boolean' },
|
|
976
|
-
optional: true,
|
|
977
|
-
nullable: true,
|
|
978
|
-
minLength: 2,
|
|
979
|
-
maxLength: 2,
|
|
980
|
-
description: 'x',
|
|
981
|
-
} as const satisfies x.Schema
|
|
982
|
-
|
|
983
|
-
const prevStruct = x
|
|
984
|
-
.array(x.boolean())
|
|
985
|
-
.description(schema.description)
|
|
986
|
-
.maxLength(schema.maxLength)
|
|
987
|
-
.minLength(schema.minLength)
|
|
988
|
-
.nullable()
|
|
989
|
-
|
|
990
|
-
const struct = prevStruct.optional()
|
|
991
|
-
|
|
992
|
-
type ExpectedKeys = StructSharedKeys
|
|
993
|
-
|
|
994
|
-
foldB: {
|
|
995
|
-
const construct = x.makeStruct(schema)
|
|
996
|
-
|
|
997
|
-
/* ensure that struct keys are reduced after application */
|
|
998
|
-
|
|
999
|
-
type StructKeys = keyof typeof struct
|
|
1000
|
-
|
|
1001
|
-
x.tCh<StructKeys, ExpectedKeys>()
|
|
1002
|
-
x.tCh<ExpectedKeys, StructKeys>()
|
|
1003
|
-
|
|
1004
|
-
type ConstructKeys = keyof typeof construct
|
|
1005
|
-
|
|
1006
|
-
x.tCh<ConstructKeys, ExpectedKeys>()
|
|
1007
|
-
x.tCh<ExpectedKeys, ConstructKeys>()
|
|
1008
|
-
|
|
1009
|
-
/* ensure that construct/struct schema types are identical */
|
|
1010
|
-
|
|
1011
|
-
type ExpectedSchema = typeof schema
|
|
1012
|
-
type StructSchema = typeof struct.__schema
|
|
1013
|
-
|
|
1014
|
-
x.tCh<StructSchema, ExpectedSchema>()
|
|
1015
|
-
x.tCh<ExpectedSchema, StructSchema>()
|
|
1016
|
-
|
|
1017
|
-
type ConstructSchema = typeof struct.__schema
|
|
1018
|
-
|
|
1019
|
-
x.tCh<ConstructSchema, ExpectedSchema>()
|
|
1020
|
-
x.tCh<ExpectedSchema, ConstructSchema>()
|
|
1021
|
-
|
|
1022
|
-
/* runtime schema check */
|
|
1023
|
-
|
|
1024
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
1025
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
1026
|
-
expect(construct.__schema === schema).toBe(false)
|
|
1027
|
-
|
|
1028
|
-
/* runtime schema parameter application immutability check */
|
|
1029
|
-
|
|
1030
|
-
expect(prevStruct.__schema === struct.__schema).toBe(false)
|
|
1031
|
-
}
|
|
1032
|
-
})
|
|
1033
|
-
})
|
|
1034
|
-
|
|
1035
|
-
describe('ERROR_CODE.invalidType (foldC, foldE)', () => {
|
|
1036
|
-
it('iterate over fixture.DATA_TYPE', () => {
|
|
1037
|
-
const schema = {
|
|
1038
|
-
type: 'array',
|
|
1039
|
-
of: { type: 'boolean' },
|
|
1040
|
-
} as const satisfies x.Schema
|
|
1041
|
-
|
|
1042
|
-
const struct = x.array(x.boolean())
|
|
1043
|
-
const source = fixture.DATA_TYPE
|
|
1044
|
-
|
|
1045
|
-
foldC: {
|
|
1046
|
-
const construct = x.makeStruct(schema)
|
|
1047
|
-
|
|
1048
|
-
for (const [kind, types] of source) {
|
|
1049
|
-
if (kind === schema.type) {
|
|
1050
|
-
continue
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
for (const subject of types) {
|
|
1054
|
-
const expectedError = [
|
|
1055
|
-
{
|
|
1056
|
-
code: x.ERROR_CODE.invalidType,
|
|
1057
|
-
schema: schema,
|
|
1058
|
-
subject: subject,
|
|
1059
|
-
path: [],
|
|
1060
|
-
},
|
|
1061
|
-
]
|
|
1062
|
-
|
|
1063
|
-
const parsedSchema = x.parse(schema, subject)
|
|
1064
|
-
const parsedConstruct = construct.parse(subject)
|
|
1065
|
-
const parsedStruct = struct.parse(subject)
|
|
1066
|
-
|
|
1067
|
-
expect(parsedSchema.error).toStrictEqual(expectedError)
|
|
1068
|
-
expect(parsedConstruct.error).toStrictEqual(expectedError)
|
|
1069
|
-
expect(parsedStruct.error).toStrictEqual(expectedError)
|
|
1070
|
-
|
|
1071
|
-
const parsedStandard = struct['~standard'].validate(subject)
|
|
1072
|
-
|
|
1073
|
-
if (parsedStandard instanceof Promise) {
|
|
1074
|
-
throw Error('Not expected')
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
expect(parsedStandard.issues).toStrictEqual([
|
|
1078
|
-
{ message: x.ERROR_CODE.invalidType, path: [] },
|
|
1079
|
-
])
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
})
|
|
1084
|
-
|
|
1085
|
-
it('InvalidSubject error of nested schema should have correct path/schema/subject', () => {
|
|
1086
|
-
const schema = {
|
|
1087
|
-
type: 'array',
|
|
1088
|
-
of: { type: 'array', of: { type: 'boolean' } },
|
|
1089
|
-
} as const satisfies x.Schema
|
|
1090
|
-
|
|
1091
|
-
const struct = x.array(x.array(x.boolean()))
|
|
1092
|
-
const samples: Array<
|
|
1093
|
-
[
|
|
1094
|
-
subj: unknown[],
|
|
1095
|
-
invalidSubj: unknown,
|
|
1096
|
-
invalidSubjSchema: x.Schema,
|
|
1097
|
-
errorPath: x.ErrorPath,
|
|
1098
|
-
]
|
|
1099
|
-
> = [
|
|
1100
|
-
[[[null, false, true]], null, schema.of.of, [0, 0]],
|
|
1101
|
-
[[[], [null, false, true]], null, schema.of.of, [1, 0]],
|
|
1102
|
-
[[[], [], [null, false, true]], null, schema.of.of, [2, 0]],
|
|
1103
|
-
[[[true, 'str', true]], 'str', schema.of.of, [0, 1]],
|
|
1104
|
-
[[[], [true, 'str', true]], 'str', schema.of.of, [1, 1]],
|
|
1105
|
-
[[[], [], [true, 'str', true]], 'str', schema.of.of, [2, 1]],
|
|
1106
|
-
[[[true, false, 69]], 69, schema.of.of, [0, 2]],
|
|
1107
|
-
[[[], [true, false, 69]], 69, schema.of.of, [1, 2]],
|
|
1108
|
-
[[[], [], [true, false, 69]], 69, schema.of.of, [2, 2]],
|
|
1109
|
-
]
|
|
1110
|
-
|
|
1111
|
-
foldE: {
|
|
1112
|
-
const construct = x.makeStruct(schema)
|
|
1113
|
-
|
|
1114
|
-
for (const [subject, invalidSubj, invalidSubjSchema, path] of samples) {
|
|
1115
|
-
const expectedError = [
|
|
1116
|
-
{
|
|
1117
|
-
path,
|
|
1118
|
-
code: x.ERROR_CODE.invalidType,
|
|
1119
|
-
schema: invalidSubjSchema,
|
|
1120
|
-
subject: invalidSubj,
|
|
1121
|
-
},
|
|
1122
|
-
]
|
|
1123
|
-
|
|
1124
|
-
const parsedSchema = x.parse(schema, subject)
|
|
1125
|
-
const parsedConstruct = construct.parse(subject)
|
|
1126
|
-
const parsedStruct = struct.parse(subject)
|
|
1127
|
-
|
|
1128
|
-
expect(parsedSchema.error).toStrictEqual(expectedError)
|
|
1129
|
-
expect(parsedConstruct.error).toStrictEqual(expectedError)
|
|
1130
|
-
expect(parsedStruct.error).toStrictEqual(expectedError)
|
|
1131
|
-
|
|
1132
|
-
const parsedStandard = struct['~standard'].validate(subject)
|
|
1133
|
-
|
|
1134
|
-
if (parsedStandard instanceof Promise) {
|
|
1135
|
-
throw Error('Not expected')
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
expect(parsedStandard.issues).toStrictEqual([
|
|
1139
|
-
{ path, message: x.ERROR_CODE.invalidType },
|
|
1140
|
-
])
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
})
|
|
1144
|
-
|
|
1145
|
-
it('multiple errors', () => {
|
|
1146
|
-
const schema = {
|
|
1147
|
-
type: 'array',
|
|
1148
|
-
of: { type: 'boolean' },
|
|
1149
|
-
} as const satisfies x.Schema
|
|
1150
|
-
|
|
1151
|
-
const struct = x.array(x.boolean())
|
|
1152
|
-
|
|
1153
|
-
const construct = x.makeStruct(schema)
|
|
1154
|
-
|
|
1155
|
-
const subject = [null, true, undefined]
|
|
1156
|
-
|
|
1157
|
-
const expectedError: x.InvalidSubject[] = [
|
|
1158
|
-
{
|
|
1159
|
-
code: x.ERROR_CODE.invalidType,
|
|
1160
|
-
path: [0],
|
|
1161
|
-
schema: schema.of,
|
|
1162
|
-
subject: null,
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
code: x.ERROR_CODE.invalidType,
|
|
1166
|
-
path: [2],
|
|
1167
|
-
schema: schema.of,
|
|
1168
|
-
subject: undefined,
|
|
1169
|
-
},
|
|
1170
|
-
]
|
|
1171
|
-
|
|
1172
|
-
const parsedSchema = x.parse(schema, subject)
|
|
1173
|
-
const parsedStruct = struct.parse(subject)
|
|
1174
|
-
const parsedConstruct = construct.parse(subject)
|
|
1175
|
-
|
|
1176
|
-
expect(parsedSchema.error).toStrictEqual(expectedError)
|
|
1177
|
-
expect(parsedStruct.error).toStrictEqual(expectedError)
|
|
1178
|
-
expect(parsedConstruct.error).toStrictEqual(expectedError)
|
|
1179
|
-
})
|
|
1180
|
-
})
|
|
1181
|
-
|
|
1182
|
-
describe('ERROR_CODE.invalidRange (foldD)', () => {
|
|
1183
|
-
it('minLength', () => {
|
|
1184
|
-
const schema = {
|
|
1185
|
-
type: 'array',
|
|
1186
|
-
of: { type: 'boolean' },
|
|
1187
|
-
minLength: 3,
|
|
1188
|
-
} as const satisfies x.Schema
|
|
1189
|
-
|
|
1190
|
-
const struct = x.array(x.boolean()).minLength(schema.minLength)
|
|
1191
|
-
const subjects = [[], [false], [false, true]]
|
|
1192
|
-
|
|
1193
|
-
foldD: {
|
|
1194
|
-
const construct = x.makeStruct(schema)
|
|
1195
|
-
|
|
1196
|
-
for (const subject of subjects) {
|
|
1197
|
-
const expectedError = [
|
|
1198
|
-
{
|
|
1199
|
-
code: x.ERROR_CODE.invalidRange,
|
|
1200
|
-
schema: schema,
|
|
1201
|
-
subject: subject,
|
|
1202
|
-
path: [],
|
|
1203
|
-
},
|
|
1204
|
-
]
|
|
1205
|
-
|
|
1206
|
-
const parsedSchema = x.parse(schema, subject)
|
|
1207
|
-
const parsedConstruct = construct.parse(subject)
|
|
1208
|
-
const parsedStruct = struct.parse(subject)
|
|
1209
|
-
|
|
1210
|
-
expect(parsedSchema.error).toStrictEqual(expectedError)
|
|
1211
|
-
expect(parsedConstruct.error).toStrictEqual(expectedError)
|
|
1212
|
-
expect(parsedStruct.error).toStrictEqual(expectedError)
|
|
1213
|
-
|
|
1214
|
-
const parsedStandard = struct['~standard'].validate(subject)
|
|
1215
|
-
|
|
1216
|
-
if (parsedStandard instanceof Promise) {
|
|
1217
|
-
throw Error('Not expected')
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
expect(parsedStandard.issues).toStrictEqual([
|
|
1221
|
-
{ message: x.ERROR_CODE.invalidRange, path: [] },
|
|
1222
|
-
])
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
})
|
|
1226
|
-
|
|
1227
|
-
it('maxLength', () => {
|
|
1228
|
-
const schema = {
|
|
1229
|
-
type: 'array',
|
|
1230
|
-
of: { type: 'boolean' },
|
|
1231
|
-
maxLength: 0,
|
|
1232
|
-
} as const satisfies x.Schema
|
|
1233
|
-
|
|
1234
|
-
const struct = x.array(x.boolean()).maxLength(schema.maxLength)
|
|
1235
|
-
const subjects = [[false], [false, true], [false, true, false]]
|
|
1236
|
-
|
|
1237
|
-
foldD: {
|
|
1238
|
-
const construct = x.makeStruct(schema)
|
|
1239
|
-
|
|
1240
|
-
for (const subject of subjects) {
|
|
1241
|
-
const expectedError = [
|
|
1242
|
-
{
|
|
1243
|
-
code: x.ERROR_CODE.invalidRange,
|
|
1244
|
-
schema: schema,
|
|
1245
|
-
subject: subject,
|
|
1246
|
-
path: [],
|
|
1247
|
-
},
|
|
1248
|
-
]
|
|
1249
|
-
|
|
1250
|
-
const parsedSchema = x.parse(schema, subject)
|
|
1251
|
-
const parsedConstruct = construct.parse(subject)
|
|
1252
|
-
const parsedStruct = struct.parse(subject)
|
|
1253
|
-
|
|
1254
|
-
expect(parsedSchema.error).toStrictEqual(expectedError)
|
|
1255
|
-
expect(parsedConstruct.error).toStrictEqual(expectedError)
|
|
1256
|
-
expect(parsedStruct.error).toStrictEqual(expectedError)
|
|
1257
|
-
|
|
1258
|
-
const parsedStandard = struct['~standard'].validate(subject)
|
|
1259
|
-
|
|
1260
|
-
if (parsedStandard instanceof Promise) {
|
|
1261
|
-
throw Error('Not expected')
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
expect(parsedStandard.issues).toStrictEqual([
|
|
1265
|
-
{ message: x.ERROR_CODE.invalidRange, path: [] },
|
|
1266
|
-
])
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
|
-
})
|
|
1270
|
-
|
|
1271
|
-
it('minLength + maxLength', () => {
|
|
1272
|
-
const schema = {
|
|
1273
|
-
type: 'array',
|
|
1274
|
-
of: { type: 'boolean' },
|
|
1275
|
-
maxLength: 2,
|
|
1276
|
-
minLength: 2,
|
|
1277
|
-
} as const satisfies x.Schema
|
|
1278
|
-
|
|
1279
|
-
const struct = x
|
|
1280
|
-
.array(x.boolean())
|
|
1281
|
-
.minLength(schema.minLength)
|
|
1282
|
-
.maxLength(schema.maxLength)
|
|
1283
|
-
|
|
1284
|
-
const subjects = [[], [false], [false, true, false]]
|
|
1285
|
-
|
|
1286
|
-
foldD: {
|
|
1287
|
-
const construct = x.makeStruct(schema)
|
|
1288
|
-
|
|
1289
|
-
for (const subject of subjects) {
|
|
1290
|
-
const expectedError = [
|
|
1291
|
-
{
|
|
1292
|
-
code: x.ERROR_CODE.invalidRange,
|
|
1293
|
-
schema: schema,
|
|
1294
|
-
subject: subject,
|
|
1295
|
-
path: [],
|
|
1296
|
-
},
|
|
1297
|
-
]
|
|
1298
|
-
|
|
1299
|
-
const parsedSchema = x.parse(schema, subject)
|
|
1300
|
-
const parsedConstruct = construct.parse(subject)
|
|
1301
|
-
const parsedStruct = struct.parse(subject)
|
|
1302
|
-
|
|
1303
|
-
expect(parsedSchema.error).toStrictEqual(expectedError)
|
|
1304
|
-
expect(parsedConstruct.error).toStrictEqual(expectedError)
|
|
1305
|
-
expect(parsedStruct.error).toStrictEqual(expectedError)
|
|
1306
|
-
|
|
1307
|
-
const parsedStandard = struct['~standard'].validate(subject)
|
|
1308
|
-
|
|
1309
|
-
if (parsedStandard instanceof Promise) {
|
|
1310
|
-
throw Error('Not expected')
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
expect(parsedStandard.issues).toStrictEqual([
|
|
1314
|
-
{ message: x.ERROR_CODE.invalidRange, path: [] },
|
|
1315
|
-
])
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
})
|
|
1319
|
-
})
|
|
1320
|
-
|
|
1321
|
-
describe('Compound schema specifics (foldA)', () => {
|
|
1322
|
-
it('nested primitive schema: optional + nullable + brand', () => {
|
|
1323
|
-
const schema = {
|
|
1324
|
-
type: 'array',
|
|
1325
|
-
of: {
|
|
1326
|
-
type: 'boolean',
|
|
1327
|
-
optional: true,
|
|
1328
|
-
nullable: true,
|
|
1329
|
-
brand: ['x', 'y'],
|
|
1330
|
-
},
|
|
1331
|
-
} as const satisfies x.Schema
|
|
1332
|
-
|
|
1333
|
-
const struct = x.array(
|
|
1334
|
-
x
|
|
1335
|
-
.boolean()
|
|
1336
|
-
.optional()
|
|
1337
|
-
.nullable()
|
|
1338
|
-
.brand(...schema.of.brand)
|
|
1339
|
-
)
|
|
1340
|
-
|
|
1341
|
-
type Branded = boolean & { __x: 'y' }
|
|
1342
|
-
type ExpectedSubj = Array<Branded | undefined | null>
|
|
1343
|
-
|
|
1344
|
-
const subjects = [
|
|
1345
|
-
[],
|
|
1346
|
-
[undefined],
|
|
1347
|
-
[null],
|
|
1348
|
-
[true as Branded],
|
|
1349
|
-
[false as Branded, undefined, null],
|
|
1350
|
-
] as const satisfies Array<ExpectedSubj>
|
|
1351
|
-
|
|
1352
|
-
foldA: {
|
|
1353
|
-
const construct = x.makeStruct(schema)
|
|
1354
|
-
|
|
1355
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
1356
|
-
|
|
1357
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
1358
|
-
|
|
1359
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
1360
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
1361
|
-
|
|
1362
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
1363
|
-
|
|
1364
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
1365
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
1366
|
-
|
|
1367
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
1368
|
-
|
|
1369
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
1370
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
1371
|
-
|
|
1372
|
-
type StandardSubj = NonNullable<
|
|
1373
|
-
(typeof struct)['~standard']['types']
|
|
1374
|
-
>['output']
|
|
1375
|
-
|
|
1376
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
1377
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
1378
|
-
|
|
1379
|
-
/* parsed either type check */
|
|
1380
|
-
|
|
1381
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
1382
|
-
|
|
1383
|
-
const parsed = x.parse(schema, undefined)
|
|
1384
|
-
|
|
1385
|
-
type SchemaParsed = typeof parsed
|
|
1386
|
-
|
|
1387
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
1388
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
1389
|
-
|
|
1390
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
1391
|
-
|
|
1392
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
1393
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
1394
|
-
|
|
1395
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
1396
|
-
|
|
1397
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
1398
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
1399
|
-
|
|
1400
|
-
type StandardParsed = Extract<
|
|
1401
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
1402
|
-
{ value: unknown }
|
|
1403
|
-
>['value']
|
|
1404
|
-
|
|
1405
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
1406
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
1407
|
-
|
|
1408
|
-
/* runtime schema check */
|
|
1409
|
-
|
|
1410
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
1411
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
1412
|
-
expect(construct.__schema === schema).toBe(false)
|
|
1413
|
-
|
|
1414
|
-
/* parse result check */
|
|
1415
|
-
|
|
1416
|
-
for (const subj of subjects) {
|
|
1417
|
-
const schemaParsed = x.parse(schema, subj)
|
|
1418
|
-
|
|
1419
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
1420
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
1421
|
-
|
|
1422
|
-
const constructParsed = construct.parse(subj)
|
|
1423
|
-
|
|
1424
|
-
expect(constructParsed.error).toBe(undefined)
|
|
1425
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
1426
|
-
|
|
1427
|
-
const structParsed = struct.parse(subj)
|
|
1428
|
-
|
|
1429
|
-
expect(structParsed.error).toBe(undefined)
|
|
1430
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
1431
|
-
|
|
1432
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
1433
|
-
|
|
1434
|
-
if (standardParsed instanceof Promise) {
|
|
1435
|
-
throw Error('Not expected')
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
if (standardParsed.issues !== undefined) {
|
|
1439
|
-
throw Error('not expected')
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
})
|
|
1446
|
-
|
|
1447
|
-
it('nested compound schema: optional + nullable', () => {
|
|
1448
|
-
const schema = {
|
|
1449
|
-
type: 'array',
|
|
1450
|
-
of: {
|
|
1451
|
-
type: 'array',
|
|
1452
|
-
of: { type: 'boolean' },
|
|
1453
|
-
optional: true,
|
|
1454
|
-
nullable: true,
|
|
1455
|
-
},
|
|
1456
|
-
} as const satisfies x.Schema
|
|
1457
|
-
|
|
1458
|
-
const struct = x.array(x.array(x.boolean()).optional().nullable())
|
|
1459
|
-
|
|
1460
|
-
type ExpectedSubj = Array<Array<boolean> | undefined | null>
|
|
1461
|
-
|
|
1462
|
-
const subjects = [
|
|
1463
|
-
[],
|
|
1464
|
-
[undefined],
|
|
1465
|
-
[null],
|
|
1466
|
-
[[]],
|
|
1467
|
-
[[true]],
|
|
1468
|
-
[[false], undefined, null],
|
|
1469
|
-
] as const satisfies Array<ExpectedSubj>
|
|
1470
|
-
|
|
1471
|
-
foldA: {
|
|
1472
|
-
const construct = x.makeStruct(schema)
|
|
1473
|
-
|
|
1474
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
1475
|
-
|
|
1476
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
1477
|
-
|
|
1478
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
1479
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
1480
|
-
|
|
1481
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
1482
|
-
|
|
1483
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
1484
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
1485
|
-
|
|
1486
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
1487
|
-
|
|
1488
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
1489
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
1490
|
-
|
|
1491
|
-
type StandardSubj = NonNullable<
|
|
1492
|
-
(typeof struct)['~standard']['types']
|
|
1493
|
-
>['output']
|
|
1494
|
-
|
|
1495
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
1496
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
1497
|
-
|
|
1498
|
-
/* parsed either type check */
|
|
1499
|
-
|
|
1500
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
1501
|
-
|
|
1502
|
-
const parsed = x.parse(schema, undefined)
|
|
1503
|
-
|
|
1504
|
-
type SchemaParsed = typeof parsed
|
|
1505
|
-
|
|
1506
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
1507
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
1508
|
-
|
|
1509
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
1510
|
-
|
|
1511
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
1512
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
1513
|
-
|
|
1514
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
1515
|
-
|
|
1516
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
1517
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
1518
|
-
|
|
1519
|
-
type StandardParsed = Extract<
|
|
1520
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
1521
|
-
{ value: unknown }
|
|
1522
|
-
>['value']
|
|
1523
|
-
|
|
1524
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
1525
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
1526
|
-
|
|
1527
|
-
/* runtime schema check */
|
|
1528
|
-
|
|
1529
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
1530
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
1531
|
-
expect(construct.__schema === schema).toBe(false)
|
|
1532
|
-
|
|
1533
|
-
/* parse result check */
|
|
1534
|
-
|
|
1535
|
-
for (const subj of subjects) {
|
|
1536
|
-
const schemaParsed = x.parse(schema, subj)
|
|
1537
|
-
|
|
1538
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
1539
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
1540
|
-
|
|
1541
|
-
const constructParsed = construct.parse(subj)
|
|
1542
|
-
|
|
1543
|
-
expect(constructParsed.error).toBe(undefined)
|
|
1544
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
1545
|
-
|
|
1546
|
-
const structParsed = struct.parse(subj)
|
|
1547
|
-
|
|
1548
|
-
expect(structParsed.error).toBe(undefined)
|
|
1549
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
1550
|
-
|
|
1551
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
1552
|
-
|
|
1553
|
-
if (standardParsed instanceof Promise) {
|
|
1554
|
-
throw Error('Not expected')
|
|
1555
|
-
}
|
|
1556
|
-
|
|
1557
|
-
if (standardParsed.issues !== undefined) {
|
|
1558
|
-
throw Error('not expected')
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
})
|
|
1565
|
-
|
|
1566
|
-
it('nested by itself (schema depth: 4)', () => {
|
|
1567
|
-
const schema = {
|
|
1568
|
-
type: 'array',
|
|
1569
|
-
of: {
|
|
1570
|
-
type: 'array',
|
|
1571
|
-
of: { type: 'array', of: { type: 'boolean' } },
|
|
1572
|
-
},
|
|
1573
|
-
} as const satisfies x.Schema
|
|
1574
|
-
|
|
1575
|
-
const struct = x.array(x.array(x.array(x.boolean())))
|
|
1576
|
-
|
|
1577
|
-
type ExpectedSubj = Array<Array<Array<boolean>>>
|
|
1578
|
-
|
|
1579
|
-
const subjects = [
|
|
1580
|
-
[[]],
|
|
1581
|
-
[[], []],
|
|
1582
|
-
[[[]]],
|
|
1583
|
-
[
|
|
1584
|
-
[[], []],
|
|
1585
|
-
[[], []],
|
|
1586
|
-
],
|
|
1587
|
-
[[[true]], [[true, false]]],
|
|
1588
|
-
] as const satisfies Array<ExpectedSubj>
|
|
1589
|
-
|
|
1590
|
-
foldA: {
|
|
1591
|
-
const construct = x.makeStruct(schema)
|
|
1592
|
-
|
|
1593
|
-
/* ensure that schema/construct/struct/~standard subject types are identical */
|
|
1594
|
-
|
|
1595
|
-
type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
|
|
1596
|
-
|
|
1597
|
-
x.tCh<ConstructSchemaSubj, ExpectedSubj>()
|
|
1598
|
-
x.tCh<ExpectedSubj, ConstructSchemaSubj>()
|
|
1599
|
-
|
|
1600
|
-
type SchemaSubj = x.Infer<typeof schema>
|
|
1601
|
-
|
|
1602
|
-
x.tCh<SchemaSubj, ExpectedSubj>()
|
|
1603
|
-
x.tCh<ExpectedSubj, SchemaSubj>()
|
|
1604
|
-
|
|
1605
|
-
type StructSubj = x.Infer<typeof struct.__schema>
|
|
1606
|
-
|
|
1607
|
-
x.tCh<StructSubj, ExpectedSubj>()
|
|
1608
|
-
x.tCh<ExpectedSubj, StructSubj>()
|
|
1609
|
-
|
|
1610
|
-
type StandardSubj = NonNullable<
|
|
1611
|
-
(typeof struct)['~standard']['types']
|
|
1612
|
-
>['output']
|
|
1613
|
-
|
|
1614
|
-
x.tCh<StandardSubj, ExpectedSubj>()
|
|
1615
|
-
x.tCh<ExpectedSubj, StandardSubj>()
|
|
1616
|
-
|
|
1617
|
-
/* parsed either type check */
|
|
1618
|
-
|
|
1619
|
-
type ExpectedParsed = x.ParseResult<ExpectedSubj>
|
|
1620
|
-
|
|
1621
|
-
const parsed = x.parse(schema, undefined)
|
|
1622
|
-
|
|
1623
|
-
type SchemaParsed = typeof parsed
|
|
1624
|
-
|
|
1625
|
-
x.tCh<SchemaParsed, ExpectedParsed>()
|
|
1626
|
-
x.tCh<ExpectedParsed, SchemaParsed>()
|
|
1627
|
-
|
|
1628
|
-
type ConstructParsed = ReturnType<typeof construct.parse>
|
|
1629
|
-
|
|
1630
|
-
x.tCh<ConstructParsed, ExpectedParsed>()
|
|
1631
|
-
x.tCh<ExpectedParsed, ConstructParsed>()
|
|
1632
|
-
|
|
1633
|
-
type StructParsed = ReturnType<typeof struct.parse>
|
|
1634
|
-
|
|
1635
|
-
x.tCh<StructParsed, ExpectedParsed>()
|
|
1636
|
-
x.tCh<ExpectedParsed, StructParsed>()
|
|
1637
|
-
|
|
1638
|
-
type StandardParsed = Extract<
|
|
1639
|
-
ReturnType<(typeof struct)['~standard']['validate']>,
|
|
1640
|
-
{ value: unknown }
|
|
1641
|
-
>['value']
|
|
1642
|
-
|
|
1643
|
-
x.tCh<StandardParsed, ExpectedSubj>()
|
|
1644
|
-
x.tCh<ExpectedSubj, StandardParsed>()
|
|
1645
|
-
|
|
1646
|
-
/* runtime schema check */
|
|
1647
|
-
|
|
1648
|
-
expect(struct.__schema).toStrictEqual(schema)
|
|
1649
|
-
expect(construct.__schema).toStrictEqual(schema)
|
|
1650
|
-
expect(construct.__schema === schema).toBe(false)
|
|
1651
|
-
|
|
1652
|
-
/* parse result check */
|
|
1653
|
-
|
|
1654
|
-
for (const subj of subjects) {
|
|
1655
|
-
const schemaParsed = x.parse(schema, subj)
|
|
1656
|
-
|
|
1657
|
-
expect(schemaParsed.error).toBe(undefined)
|
|
1658
|
-
expect(schemaParsed.data).toStrictEqual(subj)
|
|
1659
|
-
|
|
1660
|
-
const constructParsed = construct.parse(subj)
|
|
1661
|
-
|
|
1662
|
-
expect(constructParsed.error).toBe(undefined)
|
|
1663
|
-
expect(constructParsed.data).toStrictEqual(subj)
|
|
1664
|
-
|
|
1665
|
-
const structParsed = struct.parse(subj)
|
|
1666
|
-
|
|
1667
|
-
expect(structParsed.error).toBe(undefined)
|
|
1668
|
-
expect(structParsed.data).toStrictEqual(subj)
|
|
1669
|
-
|
|
1670
|
-
const standardParsed = struct['~standard'].validate(subj)
|
|
1671
|
-
|
|
1672
|
-
if (standardParsed instanceof Promise) {
|
|
1673
|
-
throw Error('Not expected')
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
if (standardParsed.issues !== undefined) {
|
|
1677
|
-
throw Error('not expected')
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
|
-
expect(standardParsed.value).toStrictEqual(subj)
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
})
|
|
1684
|
-
})
|