schematox 1.2.1 → 1.2.2

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.
Files changed (63) hide show
  1. package/dist/constants.d.ts +20 -0
  2. package/dist/constants.d.ts.map +1 -0
  3. package/dist/constants.js +22 -0
  4. package/dist/constants.js.map +1 -0
  5. package/dist/index.d.ts +10 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +9 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/parse.d.ts +5 -0
  10. package/dist/parse.d.ts.map +1 -0
  11. package/dist/parse.js +328 -0
  12. package/dist/parse.js.map +1 -0
  13. package/dist/struct.d.ts +48 -0
  14. package/dist/struct.d.ts.map +1 -0
  15. package/dist/struct.js +111 -0
  16. package/dist/struct.js.map +1 -0
  17. package/dist/types/extensions.d.ts +13 -0
  18. package/dist/types/extensions.d.ts.map +1 -0
  19. package/dist/types/extensions.js +2 -0
  20. package/dist/types/extensions.js.map +1 -0
  21. package/dist/types/infer.d.ts +35 -0
  22. package/dist/types/infer.d.ts.map +1 -0
  23. package/dist/types/infer.js +2 -0
  24. package/dist/types/infer.js.map +1 -0
  25. package/dist/types/schema.d.ts +93 -0
  26. package/dist/types/schema.d.ts.map +1 -0
  27. package/dist/types/schema.js +2 -0
  28. package/dist/types/schema.js.map +1 -0
  29. package/dist/types/standard-schema.d.ts +35 -0
  30. package/dist/types/standard-schema.d.ts.map +1 -0
  31. package/dist/types/standard-schema.js +2 -0
  32. package/dist/types/standard-schema.js.map +1 -0
  33. package/dist/types/struct.d.ts +52 -0
  34. package/dist/types/struct.d.ts.map +1 -0
  35. package/dist/types/struct.js +2 -0
  36. package/dist/types/struct.js.map +1 -0
  37. package/dist/types/utils.d.ts +41 -0
  38. package/dist/types/utils.d.ts.map +1 -0
  39. package/dist/types/utils.js +2 -0
  40. package/dist/types/utils.js.map +1 -0
  41. package/dist/utils.d.ts +9 -0
  42. package/dist/utils.d.ts.map +1 -0
  43. package/dist/utils.js +14 -0
  44. package/dist/utils.js.map +1 -0
  45. package/package.json +15 -5
  46. package/src/tests/README.md +390 -0
  47. package/src/tests/by-struct/array.test.ts +1684 -0
  48. package/src/tests/by-struct/boolean.test.ts +741 -0
  49. package/src/tests/by-struct/literal.test.ts +755 -0
  50. package/src/tests/by-struct/number.test.ts +1234 -0
  51. package/src/tests/by-struct/object.test.ts +1484 -0
  52. package/src/tests/by-struct/record.test.ts +1802 -0
  53. package/src/tests/by-struct/string.test.ts +1252 -0
  54. package/src/tests/by-struct/tuple.test.ts +1341 -0
  55. package/src/tests/by-struct/union.test.ts +1284 -0
  56. package/src/tests/fixtures.ts +53 -0
  57. package/src/tests/fold-constants.ts +247 -0
  58. package/src/tests/fold-morph.ts +49 -0
  59. package/src/tests/type.ts +1 -0
  60. package/src/tests/types/extensions.test.ts +117 -0
  61. package/src/tests/types/infer.test.ts +1413 -0
  62. package/src/tests/utils.test.ts +191 -0
  63. package/CHANGELOG.md +0 -52
@@ -0,0 +1,1341 @@
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: 'tuple',
10
+ of: [{ type: 'boolean' }, { type: 'literal', of: 0 }],
11
+ } as const satisfies x.Schema
12
+
13
+ const struct = x.tuple([x.boolean(), x.literal(0)])
14
+
15
+ type ExpectedSubj = [boolean, 0]
16
+
17
+ const subjects: Array<ExpectedSubj> = [
18
+ [false, 0],
19
+ [true, 0],
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: 'tuple',
120
+ of: [{ type: 'boolean' }, { type: 'literal', of: 0 }],
121
+ optional: true,
122
+ } as const satisfies x.Schema
123
+
124
+ const struct = x.tuple([x.boolean(), x.literal(0)]).optional()
125
+
126
+ type ExpectedSubj = [boolean, 0] | undefined
127
+
128
+ const subjects: Array<ExpectedSubj> = [[false, 0], [true, 0], undefined]
129
+
130
+ foldA: {
131
+ const construct = x.makeStruct(schema)
132
+
133
+ /* ensure that schema/construct/struct/~standard subject types are identical */
134
+
135
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
136
+
137
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
138
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
139
+
140
+ type SchemaSubj = x.Infer<typeof schema>
141
+
142
+ x.tCh<SchemaSubj, ExpectedSubj>()
143
+ x.tCh<ExpectedSubj, SchemaSubj>()
144
+
145
+ type StructSubj = x.Infer<typeof struct.__schema>
146
+
147
+ x.tCh<StructSubj, ExpectedSubj>()
148
+ x.tCh<ExpectedSubj, StructSubj>()
149
+
150
+ type StandardSubj = NonNullable<
151
+ (typeof struct)['~standard']['types']
152
+ >['output']
153
+
154
+ x.tCh<StandardSubj, ExpectedSubj>()
155
+ x.tCh<ExpectedSubj, StandardSubj>()
156
+
157
+ /* parsed either type check */
158
+
159
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
160
+
161
+ const parsed = x.parse(schema, undefined)
162
+
163
+ type SchemaParsed = typeof parsed
164
+
165
+ x.tCh<SchemaParsed, ExpectedParsed>()
166
+ x.tCh<ExpectedParsed, SchemaParsed>()
167
+
168
+ type ConstructParsed = ReturnType<typeof construct.parse>
169
+
170
+ x.tCh<ConstructParsed, ExpectedParsed>()
171
+ x.tCh<ExpectedParsed, ConstructParsed>()
172
+
173
+ type StructParsed = ReturnType<typeof struct.parse>
174
+
175
+ x.tCh<StructParsed, ExpectedParsed>()
176
+ x.tCh<ExpectedParsed, StructParsed>()
177
+
178
+ type StandardParsed = Extract<
179
+ ReturnType<(typeof struct)['~standard']['validate']>,
180
+ { value: unknown }
181
+ >['value']
182
+
183
+ x.tCh<StandardParsed, ExpectedSubj>()
184
+ x.tCh<ExpectedSubj, StandardParsed>()
185
+
186
+ /* runtime schema check */
187
+
188
+ expect(struct.__schema).toStrictEqual(schema)
189
+ expect(construct.__schema).toStrictEqual(schema)
190
+ expect(construct.__schema === schema).toBe(false)
191
+
192
+ /* parse result check */
193
+
194
+ for (const subj of subjects) {
195
+ const schemaParsed = x.parse(schema, subj)
196
+
197
+ expect(schemaParsed.error).toBe(undefined)
198
+ expect(schemaParsed.data).toStrictEqual(subj)
199
+
200
+ const constructParsed = construct.parse(subj)
201
+
202
+ expect(constructParsed.error).toBe(undefined)
203
+ expect(constructParsed.data).toStrictEqual(subj)
204
+
205
+ const structParsed = struct.parse(subj)
206
+
207
+ expect(structParsed.error).toBe(undefined)
208
+ expect(structParsed.data).toStrictEqual(subj)
209
+
210
+ const standardParsed = struct['~standard'].validate(subj)
211
+
212
+ if (standardParsed instanceof Promise) {
213
+ throw Error('Not expected')
214
+ }
215
+
216
+ if (standardParsed.issues !== undefined) {
217
+ throw Error('not expected')
218
+ }
219
+
220
+ expect(standardParsed.value).toStrictEqual(subj)
221
+ }
222
+ }
223
+ })
224
+
225
+ it('nullable', () => {
226
+ const schema = {
227
+ type: 'tuple',
228
+ of: [{ type: 'boolean' }, { type: 'literal', of: 0 }],
229
+ nullable: true,
230
+ } as const satisfies x.Schema
231
+
232
+ const struct = x.tuple([x.boolean(), x.literal(0)]).nullable()
233
+
234
+ type ExpectedSubj = [boolean, 0] | null
235
+
236
+ const subjects: Array<ExpectedSubj> = [[false, 0], [true, 0], null]
237
+
238
+ foldA: {
239
+ const construct = x.makeStruct(schema)
240
+
241
+ /* ensure that schema/construct/struct/~standard subject types are identical */
242
+
243
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
244
+
245
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
246
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
247
+
248
+ type SchemaSubj = x.Infer<typeof schema>
249
+
250
+ x.tCh<SchemaSubj, ExpectedSubj>()
251
+ x.tCh<ExpectedSubj, SchemaSubj>()
252
+
253
+ type StructSubj = x.Infer<typeof struct.__schema>
254
+
255
+ x.tCh<StructSubj, ExpectedSubj>()
256
+ x.tCh<ExpectedSubj, StructSubj>()
257
+
258
+ type StandardSubj = NonNullable<
259
+ (typeof struct)['~standard']['types']
260
+ >['output']
261
+
262
+ x.tCh<StandardSubj, ExpectedSubj>()
263
+ x.tCh<ExpectedSubj, StandardSubj>()
264
+
265
+ /* parsed either type check */
266
+
267
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
268
+
269
+ const parsed = x.parse(schema, undefined)
270
+
271
+ type SchemaParsed = typeof parsed
272
+
273
+ x.tCh<SchemaParsed, ExpectedParsed>()
274
+ x.tCh<ExpectedParsed, SchemaParsed>()
275
+
276
+ type ConstructParsed = ReturnType<typeof construct.parse>
277
+
278
+ x.tCh<ConstructParsed, ExpectedParsed>()
279
+ x.tCh<ExpectedParsed, ConstructParsed>()
280
+
281
+ type StructParsed = ReturnType<typeof struct.parse>
282
+
283
+ x.tCh<StructParsed, ExpectedParsed>()
284
+ x.tCh<ExpectedParsed, StructParsed>()
285
+
286
+ type StandardParsed = Extract<
287
+ ReturnType<(typeof struct)['~standard']['validate']>,
288
+ { value: unknown }
289
+ >['value']
290
+
291
+ x.tCh<StandardParsed, ExpectedSubj>()
292
+ x.tCh<ExpectedSubj, StandardParsed>()
293
+
294
+ /* runtime schema check */
295
+
296
+ expect(struct.__schema).toStrictEqual(schema)
297
+ expect(construct.__schema).toStrictEqual(schema)
298
+ expect(construct.__schema === schema).toBe(false)
299
+
300
+ /* parse result check */
301
+
302
+ for (const subj of subjects) {
303
+ const schemaParsed = x.parse(schema, subj)
304
+
305
+ expect(schemaParsed.error).toBe(undefined)
306
+ expect(schemaParsed.data).toStrictEqual(subj)
307
+
308
+ const constructParsed = construct.parse(subj)
309
+
310
+ expect(constructParsed.error).toBe(undefined)
311
+ expect(constructParsed.data).toStrictEqual(subj)
312
+
313
+ const structParsed = struct.parse(subj)
314
+
315
+ expect(structParsed.error).toBe(undefined)
316
+ expect(structParsed.data).toStrictEqual(subj)
317
+
318
+ const standardParsed = struct['~standard'].validate(subj)
319
+
320
+ if (standardParsed instanceof Promise) {
321
+ throw Error('Not expected')
322
+ }
323
+
324
+ if (standardParsed.issues !== undefined) {
325
+ throw Error('not expected')
326
+ }
327
+
328
+ expect(standardParsed.value).toStrictEqual(subj)
329
+ }
330
+ }
331
+ })
332
+
333
+ it('optional + nullable', () => {
334
+ const schema = {
335
+ type: 'tuple',
336
+ of: [{ type: 'boolean' }, { type: 'literal', of: 0 }],
337
+ optional: true,
338
+ nullable: true,
339
+ } as const satisfies x.Schema
340
+
341
+ const struct = x
342
+ .tuple([x.boolean(), x.literal(0)])
343
+ .optional()
344
+ .nullable()
345
+
346
+ type ExpectedSubj = [boolean, 0] | undefined | null
347
+
348
+ const subjects: Array<ExpectedSubj> = [
349
+ [false, 0],
350
+ [true, 0],
351
+ undefined,
352
+ null,
353
+ ]
354
+
355
+ foldA: {
356
+ const construct = x.makeStruct(schema)
357
+
358
+ /* ensure that schema/construct/struct/~standard subject types are identical */
359
+
360
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
361
+
362
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
363
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
364
+
365
+ type SchemaSubj = x.Infer<typeof schema>
366
+
367
+ x.tCh<SchemaSubj, ExpectedSubj>()
368
+ x.tCh<ExpectedSubj, SchemaSubj>()
369
+
370
+ type StructSubj = x.Infer<typeof struct.__schema>
371
+
372
+ x.tCh<StructSubj, ExpectedSubj>()
373
+ x.tCh<ExpectedSubj, StructSubj>()
374
+
375
+ type StandardSubj = NonNullable<
376
+ (typeof struct)['~standard']['types']
377
+ >['output']
378
+
379
+ x.tCh<StandardSubj, ExpectedSubj>()
380
+ x.tCh<ExpectedSubj, StandardSubj>()
381
+
382
+ /* parsed either type check */
383
+
384
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
385
+
386
+ const parsed = x.parse(schema, undefined)
387
+
388
+ type SchemaParsed = typeof parsed
389
+
390
+ x.tCh<SchemaParsed, ExpectedParsed>()
391
+ x.tCh<ExpectedParsed, SchemaParsed>()
392
+
393
+ type ConstructParsed = ReturnType<typeof construct.parse>
394
+
395
+ x.tCh<ConstructParsed, ExpectedParsed>()
396
+ x.tCh<ExpectedParsed, ConstructParsed>()
397
+
398
+ type StructParsed = ReturnType<typeof struct.parse>
399
+
400
+ x.tCh<StructParsed, ExpectedParsed>()
401
+ x.tCh<ExpectedParsed, StructParsed>()
402
+
403
+ type StandardParsed = Extract<
404
+ ReturnType<(typeof struct)['~standard']['validate']>,
405
+ { value: unknown }
406
+ >['value']
407
+
408
+ x.tCh<StandardParsed, ExpectedSubj>()
409
+ x.tCh<ExpectedSubj, StandardParsed>()
410
+
411
+ /* runtime schema check */
412
+
413
+ expect(struct.__schema).toStrictEqual(schema)
414
+ expect(construct.__schema).toStrictEqual(schema)
415
+ expect(construct.__schema === schema).toBe(false)
416
+
417
+ /* parse result check */
418
+
419
+ for (const subj of subjects) {
420
+ const schemaParsed = x.parse(schema, subj)
421
+
422
+ expect(schemaParsed.error).toBe(undefined)
423
+ expect(schemaParsed.data).toStrictEqual(subj)
424
+
425
+ const constructParsed = construct.parse(subj)
426
+
427
+ expect(constructParsed.error).toBe(undefined)
428
+ expect(constructParsed.data).toStrictEqual(subj)
429
+
430
+ const structParsed = struct.parse(subj)
431
+
432
+ expect(structParsed.error).toBe(undefined)
433
+ expect(structParsed.data).toStrictEqual(subj)
434
+
435
+ const standardParsed = struct['~standard'].validate(subj)
436
+
437
+ if (standardParsed instanceof Promise) {
438
+ throw Error('Not expected')
439
+ }
440
+
441
+ if (standardParsed.issues !== undefined) {
442
+ throw Error('not expected')
443
+ }
444
+
445
+ expect(standardParsed.value).toStrictEqual(subj)
446
+ }
447
+ }
448
+ })
449
+ })
450
+
451
+ describe('Struct parameter keys reduction and schema immutability (foldB)', () => {
452
+ it('optional', () => {
453
+ const schema = {
454
+ type: 'tuple',
455
+ of: [{ type: 'boolean' }],
456
+ optional: true,
457
+ } as const satisfies x.Schema
458
+
459
+ const prevStruct = x.tuple([x.boolean()])
460
+ const struct = prevStruct.optional()
461
+
462
+ type ExpectedKeys = StructSharedKeys | 'description' | 'nullable'
463
+
464
+ foldB: {
465
+ const construct = x.makeStruct(schema)
466
+
467
+ /* ensure that struct keys are reduced after application */
468
+
469
+ type StructKeys = keyof typeof struct
470
+
471
+ x.tCh<StructKeys, ExpectedKeys>()
472
+ x.tCh<ExpectedKeys, StructKeys>()
473
+
474
+ type ConstructKeys = keyof typeof construct
475
+
476
+ x.tCh<ConstructKeys, ExpectedKeys>()
477
+ x.tCh<ExpectedKeys, ConstructKeys>()
478
+
479
+ /* ensure that construct/struct schema types are identical */
480
+
481
+ type ExpectedSchema = typeof schema
482
+ type StructSchema = typeof struct.__schema
483
+
484
+ x.tCh<StructSchema, ExpectedSchema>()
485
+ x.tCh<ExpectedSchema, StructSchema>()
486
+
487
+ type ConstructSchema = typeof struct.__schema
488
+
489
+ x.tCh<ConstructSchema, ExpectedSchema>()
490
+ x.tCh<ExpectedSchema, ConstructSchema>()
491
+
492
+ /* runtime schema check */
493
+
494
+ expect(struct.__schema).toStrictEqual(schema)
495
+ expect(construct.__schema).toStrictEqual(schema)
496
+ expect(construct.__schema === schema).toBe(false)
497
+
498
+ /* runtime schema parameter application immutability check */
499
+
500
+ expect(prevStruct.__schema === struct.__schema).toBe(false)
501
+ }
502
+ })
503
+
504
+ it('optional + nullable', () => {
505
+ const schema = {
506
+ type: 'tuple',
507
+ of: [{ type: 'boolean' }],
508
+ optional: true,
509
+ nullable: true,
510
+ } as const satisfies x.Schema
511
+
512
+ const prevStruct = x.tuple([x.boolean()]).optional()
513
+ const struct = prevStruct.nullable()
514
+
515
+ type ExpectedKeys = StructSharedKeys | 'description'
516
+
517
+ foldB: {
518
+ const construct = x.makeStruct(schema)
519
+
520
+ /* ensure that struct keys are reduced after application */
521
+
522
+ type StructKeys = keyof typeof struct
523
+
524
+ x.tCh<StructKeys, ExpectedKeys>()
525
+ x.tCh<ExpectedKeys, StructKeys>()
526
+
527
+ type ConstructKeys = keyof typeof construct
528
+
529
+ x.tCh<ConstructKeys, ExpectedKeys>()
530
+ x.tCh<ExpectedKeys, ConstructKeys>()
531
+
532
+ /* ensure that construct/struct schema types are identical */
533
+
534
+ type ExpectedSchema = typeof schema
535
+ type StructSchema = typeof struct.__schema
536
+
537
+ x.tCh<StructSchema, ExpectedSchema>()
538
+ x.tCh<ExpectedSchema, StructSchema>()
539
+
540
+ type ConstructSchema = typeof struct.__schema
541
+
542
+ x.tCh<ConstructSchema, ExpectedSchema>()
543
+ x.tCh<ExpectedSchema, ConstructSchema>()
544
+
545
+ /* runtime schema check */
546
+
547
+ expect(struct.__schema).toStrictEqual(schema)
548
+ expect(construct.__schema).toStrictEqual(schema)
549
+ expect(construct.__schema === schema).toBe(false)
550
+
551
+ /* runtime schema parameter application immutability check */
552
+
553
+ expect(prevStruct.__schema === struct.__schema).toBe(false)
554
+ }
555
+ })
556
+
557
+ it('optional + nullable + description', () => {
558
+ const schema = {
559
+ type: 'tuple',
560
+ of: [{ type: 'boolean' }],
561
+ optional: true,
562
+ nullable: true,
563
+ description: 'description-value',
564
+ } as const satisfies x.Schema
565
+
566
+ const prevStruct = x.tuple([x.boolean()]).optional().nullable()
567
+ const struct = prevStruct.description(schema.description)
568
+
569
+ type ExpectedKeys = StructSharedKeys
570
+
571
+ foldB: {
572
+ const construct = x.makeStruct(schema)
573
+
574
+ /* ensure that struct keys are reduced after application */
575
+
576
+ type StructKeys = keyof typeof struct
577
+
578
+ x.tCh<StructKeys, ExpectedKeys>()
579
+ x.tCh<ExpectedKeys, StructKeys>()
580
+
581
+ type ConstructKeys = keyof typeof construct
582
+
583
+ x.tCh<ConstructKeys, ExpectedKeys>()
584
+ x.tCh<ExpectedKeys, ConstructKeys>()
585
+
586
+ /* ensure that construct/struct schema types are identical */
587
+
588
+ type ExpectedSchema = typeof schema
589
+ type StructSchema = typeof struct.__schema
590
+
591
+ x.tCh<StructSchema, ExpectedSchema>()
592
+ x.tCh<ExpectedSchema, StructSchema>()
593
+
594
+ type ConstructSchema = typeof struct.__schema
595
+
596
+ x.tCh<ConstructSchema, ExpectedSchema>()
597
+ x.tCh<ExpectedSchema, ConstructSchema>()
598
+
599
+ /* runtime schema check */
600
+
601
+ expect(struct.__schema).toStrictEqual(schema)
602
+ expect(construct.__schema).toStrictEqual(schema)
603
+ expect(construct.__schema === schema).toBe(false)
604
+
605
+ /* runtime schema parameter application immutability check */
606
+
607
+ expect(prevStruct.__schema === struct.__schema).toBe(false)
608
+ }
609
+ })
610
+
611
+ it('description + nullable + optional', () => {
612
+ const schema = {
613
+ type: 'tuple',
614
+ of: [{ type: 'boolean' }],
615
+ optional: true,
616
+ nullable: true,
617
+ description: 'description-value',
618
+ } as const satisfies x.Schema
619
+
620
+ const prevStruct = x
621
+ .tuple([x.boolean()])
622
+ .description(schema.description)
623
+ .nullable()
624
+
625
+ const struct = prevStruct.optional()
626
+
627
+ type ExpectedKeys = StructSharedKeys
628
+
629
+ foldB: {
630
+ const construct = x.makeStruct(schema)
631
+
632
+ /* ensure that struct keys are reduced after application */
633
+
634
+ type StructKeys = keyof typeof struct
635
+
636
+ x.tCh<StructKeys, ExpectedKeys>()
637
+ x.tCh<ExpectedKeys, StructKeys>()
638
+
639
+ type ConstructKeys = keyof typeof construct
640
+
641
+ x.tCh<ConstructKeys, ExpectedKeys>()
642
+ x.tCh<ExpectedKeys, ConstructKeys>()
643
+
644
+ /* ensure that construct/struct schema types are identical */
645
+
646
+ type ExpectedSchema = typeof schema
647
+ type StructSchema = typeof struct.__schema
648
+
649
+ x.tCh<StructSchema, ExpectedSchema>()
650
+ x.tCh<ExpectedSchema, StructSchema>()
651
+
652
+ type ConstructSchema = typeof struct.__schema
653
+
654
+ x.tCh<ConstructSchema, ExpectedSchema>()
655
+ x.tCh<ExpectedSchema, ConstructSchema>()
656
+
657
+ /* runtime schema check */
658
+
659
+ expect(struct.__schema).toStrictEqual(schema)
660
+ expect(construct.__schema).toStrictEqual(schema)
661
+ expect(construct.__schema === schema).toBe(false)
662
+
663
+ /* runtime schema parameter application immutability check */
664
+
665
+ expect(prevStruct.__schema === struct.__schema).toBe(false)
666
+ }
667
+ })
668
+ })
669
+
670
+ describe('ERROR_CODE.invalidType (foldC, foldE)', () => {
671
+ it('iterate over fixture.DATA_TYPE', () => {
672
+ const schema = {
673
+ type: 'tuple',
674
+ of: [{ type: 'boolean' }],
675
+ } as const satisfies x.Schema
676
+
677
+ const struct = x.tuple([x.boolean()])
678
+ const source = fixture.DATA_TYPE.filter(([kind]) => kind !== 'array')
679
+
680
+ foldC: {
681
+ const construct = x.makeStruct(schema)
682
+
683
+ for (const [kind, types] of source) {
684
+ if (kind === schema.type) {
685
+ continue
686
+ }
687
+
688
+ for (const subject of types) {
689
+ const expectedError = [
690
+ {
691
+ code: x.ERROR_CODE.invalidType,
692
+ schema: schema,
693
+ subject: subject,
694
+ path: [],
695
+ },
696
+ ]
697
+
698
+ const parsedSchema = x.parse(schema, subject)
699
+ const parsedConstruct = construct.parse(subject)
700
+ const parsedStruct = struct.parse(subject)
701
+
702
+ expect(parsedSchema.error).toStrictEqual(expectedError)
703
+ expect(parsedConstruct.error).toStrictEqual(expectedError)
704
+ expect(parsedStruct.error).toStrictEqual(expectedError)
705
+
706
+ const parsedStandard = struct['~standard'].validate(subject)
707
+
708
+ if (parsedStandard instanceof Promise) {
709
+ throw Error('Not expected')
710
+ }
711
+
712
+ expect(parsedStandard.issues).toStrictEqual([
713
+ { message: x.ERROR_CODE.invalidType, path: [] },
714
+ ])
715
+ }
716
+ }
717
+ }
718
+ })
719
+
720
+ it('InvalidSubject error of nested schema should have correct path/schema/subject', () => {
721
+ const schema = {
722
+ type: 'record',
723
+ of: {
724
+ type: 'array',
725
+ of: {
726
+ type: 'object',
727
+ of: {
728
+ y: {
729
+ type: 'tuple',
730
+ of: [{ type: 'number' }, { type: 'literal', of: '_' }],
731
+ },
732
+ },
733
+ },
734
+ },
735
+ } as const satisfies x.Schema
736
+
737
+ const struct = x.record(
738
+ x.array(x.object({ y: x.tuple([x.number(), x.literal('_')]) }))
739
+ )
740
+
741
+ // prettier-ignore
742
+ const samples: Array<[
743
+ subj: Record<string, Array<{ y: unknown }>>,
744
+ invalidSubj: unknown,
745
+ invalidSubjSchema: x.Schema,
746
+ errorPath: x.ErrorPath,
747
+ ]
748
+ > = [
749
+ [{ x: [{ y: [0, '+'] }, { y: [0, '_'] }, { y: [0, '_'] }] }, '+', schema.of.of.of.y.of[1], ['x', 0, 'y', 1]],
750
+ [{ x: [{ y: [0, '_'] }, { y: [0, '+'] }, { y: [0, '_'] }] }, '+', schema.of.of.of.y.of[1], ['x', 1, 'y', 1]],
751
+ [{ x: [{ y: [0, '_'] }, { y: [0, '_'] }, { y: [0, '+'] }] }, '+', schema.of.of.of.y.of[1], ['x', 2, 'y', 1]],
752
+ ]
753
+
754
+ foldE: {
755
+ const construct = x.makeStruct(schema)
756
+
757
+ for (const [subject, invalidSubj, invalidSubjSchema, path] of samples) {
758
+ const expectedError = [
759
+ {
760
+ path,
761
+ code: x.ERROR_CODE.invalidType,
762
+ schema: invalidSubjSchema,
763
+ subject: invalidSubj,
764
+ },
765
+ ]
766
+
767
+ const parsedSchema = x.parse(schema, subject)
768
+ const parsedConstruct = construct.parse(subject)
769
+ const parsedStruct = struct.parse(subject)
770
+
771
+ expect(parsedSchema.error).toStrictEqual(expectedError)
772
+ expect(parsedConstruct.error).toStrictEqual(expectedError)
773
+ expect(parsedStruct.error).toStrictEqual(expectedError)
774
+
775
+ const parsedStandard = struct['~standard'].validate(subject)
776
+
777
+ if (parsedStandard instanceof Promise) {
778
+ throw Error('Not expected')
779
+ }
780
+
781
+ expect(parsedStandard.issues).toStrictEqual([
782
+ { path, message: x.ERROR_CODE.invalidType },
783
+ ])
784
+ }
785
+ }
786
+ })
787
+
788
+ it('multiple errors', () => {
789
+ const schema = {
790
+ type: 'tuple',
791
+ of: [{ type: 'boolean' }, { type: 'literal', of: 'x' }],
792
+ } as const satisfies x.Schema
793
+
794
+ const struct = x.tuple([x.boolean(), x.literal('x')])
795
+
796
+ const construct = x.makeStruct(schema)
797
+
798
+ const subject = ['A', 'B']
799
+
800
+ const expectedError: x.InvalidSubject[] = [
801
+ {
802
+ code: x.ERROR_CODE.invalidType,
803
+ path: [0],
804
+ schema: schema.of[0],
805
+ subject: 'A',
806
+ },
807
+ {
808
+ code: x.ERROR_CODE.invalidType,
809
+ path: [1],
810
+ schema: schema.of[1],
811
+ subject: 'B',
812
+ },
813
+ ]
814
+
815
+ const parsedSchema = x.parse(schema, subject)
816
+ const parsedStruct = struct.parse(subject)
817
+ const parsedConstruct = construct.parse(subject)
818
+
819
+ expect(parsedSchema.error).toStrictEqual(expectedError)
820
+ expect(parsedStruct.error).toStrictEqual(expectedError)
821
+ expect(parsedConstruct.error).toStrictEqual(expectedError)
822
+ })
823
+ })
824
+
825
+ describe('Compound schema specifics (foldA)', () => {
826
+ it('nested primitive schema: optional + nullable + brand', () => {
827
+ const schema = {
828
+ type: 'tuple',
829
+ of: [
830
+ {
831
+ type: 'boolean',
832
+ optional: true,
833
+ nullable: true,
834
+ brand: ['x', 'y'],
835
+ },
836
+ ],
837
+ } as const satisfies x.Schema
838
+
839
+ const struct = x.tuple([
840
+ x
841
+ .boolean()
842
+ .optional()
843
+ .nullable()
844
+ .brand(...schema.of[0].brand),
845
+ ])
846
+
847
+ type Branded = boolean & { __x: 'y' }
848
+ type ExpectedSubj = [Branded | undefined | null]
849
+
850
+ const subjects = [
851
+ [true as Branded],
852
+ [false as Branded],
853
+ [undefined],
854
+ [null],
855
+ ] as const satisfies Array<ExpectedSubj>
856
+
857
+ foldA: {
858
+ const construct = x.makeStruct(schema)
859
+
860
+ /* ensure that schema/construct/struct/~standard subject types are identical */
861
+
862
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
863
+
864
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
865
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
866
+
867
+ type SchemaSubj = x.Infer<typeof schema>
868
+
869
+ x.tCh<SchemaSubj, ExpectedSubj>()
870
+ x.tCh<ExpectedSubj, SchemaSubj>()
871
+
872
+ type StructSubj = x.Infer<typeof struct.__schema>
873
+
874
+ x.tCh<StructSubj, ExpectedSubj>()
875
+ x.tCh<ExpectedSubj, StructSubj>()
876
+
877
+ type StandardSubj = NonNullable<
878
+ (typeof struct)['~standard']['types']
879
+ >['output']
880
+
881
+ x.tCh<StandardSubj, ExpectedSubj>()
882
+ x.tCh<ExpectedSubj, StandardSubj>()
883
+
884
+ /* parsed either type check */
885
+
886
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
887
+
888
+ const parsed = x.parse(schema, undefined)
889
+
890
+ type SchemaParsed = typeof parsed
891
+
892
+ x.tCh<SchemaParsed, ExpectedParsed>()
893
+ x.tCh<ExpectedParsed, SchemaParsed>()
894
+
895
+ type ConstructParsed = ReturnType<typeof construct.parse>
896
+
897
+ x.tCh<ConstructParsed, ExpectedParsed>()
898
+ x.tCh<ExpectedParsed, ConstructParsed>()
899
+
900
+ type StructParsed = ReturnType<typeof struct.parse>
901
+
902
+ x.tCh<StructParsed, ExpectedParsed>()
903
+ x.tCh<ExpectedParsed, StructParsed>()
904
+
905
+ type StandardParsed = Extract<
906
+ ReturnType<(typeof struct)['~standard']['validate']>,
907
+ { value: unknown }
908
+ >['value']
909
+
910
+ x.tCh<StandardParsed, ExpectedSubj>()
911
+ x.tCh<ExpectedSubj, StandardParsed>()
912
+
913
+ /* runtime schema check */
914
+
915
+ expect(struct.__schema).toStrictEqual(schema)
916
+ expect(construct.__schema).toStrictEqual(schema)
917
+ expect(construct.__schema === schema).toBe(false)
918
+
919
+ /* parse result check */
920
+
921
+ for (const subj of subjects) {
922
+ const schemaParsed = x.parse(schema, subj)
923
+
924
+ expect(schemaParsed.error).toBe(undefined)
925
+ expect(schemaParsed.data).toStrictEqual(subj)
926
+
927
+ const constructParsed = construct.parse(subj)
928
+
929
+ expect(constructParsed.error).toBe(undefined)
930
+ expect(constructParsed.data).toStrictEqual(subj)
931
+
932
+ const structParsed = struct.parse(subj)
933
+
934
+ expect(structParsed.error).toBe(undefined)
935
+ expect(structParsed.data).toStrictEqual(subj)
936
+
937
+ const standardParsed = struct['~standard'].validate(subj)
938
+
939
+ if (standardParsed instanceof Promise) {
940
+ throw Error('Not expected')
941
+ }
942
+
943
+ if (standardParsed.issues !== undefined) {
944
+ throw Error('not expected')
945
+ }
946
+
947
+ expect(standardParsed.value).toStrictEqual(subj)
948
+ }
949
+ }
950
+ })
951
+
952
+ it('nested compound schema: optional + nullable', () => {
953
+ const schema = {
954
+ type: 'tuple',
955
+ of: [
956
+ {
957
+ type: 'array',
958
+ of: { type: 'boolean' },
959
+ optional: true,
960
+ nullable: true,
961
+ },
962
+ ],
963
+ } as const satisfies x.Schema
964
+
965
+ const struct = x.tuple([x.array(x.boolean()).optional().nullable()])
966
+
967
+ type ExpectedSubj = [Array<boolean> | undefined | null]
968
+
969
+ const subjects = [
970
+ [undefined],
971
+ [null],
972
+ [[true]],
973
+ ] as const satisfies Array<ExpectedSubj>
974
+
975
+ foldA: {
976
+ const construct = x.makeStruct(schema)
977
+
978
+ /* ensure that schema/construct/struct/~standard subject types are identical */
979
+
980
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
981
+
982
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
983
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
984
+
985
+ type SchemaSubj = x.Infer<typeof schema>
986
+
987
+ x.tCh<SchemaSubj, ExpectedSubj>()
988
+ x.tCh<ExpectedSubj, SchemaSubj>()
989
+
990
+ type StructSubj = x.Infer<typeof struct.__schema>
991
+
992
+ x.tCh<StructSubj, ExpectedSubj>()
993
+ x.tCh<ExpectedSubj, StructSubj>()
994
+
995
+ type StandardSubj = NonNullable<
996
+ (typeof struct)['~standard']['types']
997
+ >['output']
998
+
999
+ x.tCh<StandardSubj, ExpectedSubj>()
1000
+ x.tCh<ExpectedSubj, StandardSubj>()
1001
+
1002
+ /* parsed either type check */
1003
+
1004
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
1005
+
1006
+ const parsed = x.parse(schema, undefined)
1007
+
1008
+ type SchemaParsed = typeof parsed
1009
+
1010
+ x.tCh<SchemaParsed, ExpectedParsed>()
1011
+ x.tCh<ExpectedParsed, SchemaParsed>()
1012
+
1013
+ type ConstructParsed = ReturnType<typeof construct.parse>
1014
+
1015
+ x.tCh<ConstructParsed, ExpectedParsed>()
1016
+ x.tCh<ExpectedParsed, ConstructParsed>()
1017
+
1018
+ type StructParsed = ReturnType<typeof struct.parse>
1019
+
1020
+ x.tCh<StructParsed, ExpectedParsed>()
1021
+ x.tCh<ExpectedParsed, StructParsed>()
1022
+
1023
+ type StandardParsed = Extract<
1024
+ ReturnType<(typeof struct)['~standard']['validate']>,
1025
+ { value: unknown }
1026
+ >['value']
1027
+
1028
+ x.tCh<StandardParsed, ExpectedSubj>()
1029
+ x.tCh<ExpectedSubj, StandardParsed>()
1030
+
1031
+ /* runtime schema check */
1032
+
1033
+ expect(struct.__schema).toStrictEqual(schema)
1034
+ expect(construct.__schema).toStrictEqual(schema)
1035
+ expect(construct.__schema === schema).toBe(false)
1036
+
1037
+ /* parse result check */
1038
+
1039
+ for (const subj of subjects) {
1040
+ const schemaParsed = x.parse(schema, subj)
1041
+
1042
+ expect(schemaParsed.error).toBe(undefined)
1043
+ expect(schemaParsed.data).toStrictEqual(subj)
1044
+
1045
+ const constructParsed = construct.parse(subj)
1046
+
1047
+ expect(constructParsed.error).toBe(undefined)
1048
+ expect(constructParsed.data).toStrictEqual(subj)
1049
+
1050
+ const structParsed = struct.parse(subj)
1051
+
1052
+ expect(structParsed.error).toBe(undefined)
1053
+ expect(structParsed.data).toStrictEqual(subj)
1054
+
1055
+ const standardParsed = struct['~standard'].validate(subj)
1056
+
1057
+ if (standardParsed instanceof Promise) {
1058
+ throw Error('Not expected')
1059
+ }
1060
+
1061
+ if (standardParsed.issues !== undefined) {
1062
+ throw Error('not expected')
1063
+ }
1064
+
1065
+ expect(standardParsed.value).toStrictEqual(subj)
1066
+ }
1067
+ }
1068
+ })
1069
+
1070
+ it('nested by itself (schema depth: 4)', () => {
1071
+ const schema = {
1072
+ type: 'tuple',
1073
+ of: [
1074
+ {
1075
+ type: 'tuple',
1076
+ of: [
1077
+ {
1078
+ type: 'tuple',
1079
+ of: [{ type: 'boolean' }],
1080
+ },
1081
+ ],
1082
+ },
1083
+ ],
1084
+ } as const satisfies x.Schema
1085
+
1086
+ const struct = x.tuple([x.tuple([x.tuple([x.boolean()])])])
1087
+
1088
+ type ExpectedSubj = [[[boolean]]]
1089
+
1090
+ const subjects = [
1091
+ [[[true]]],
1092
+ [[[false]]],
1093
+ ] as const satisfies Array<ExpectedSubj>
1094
+
1095
+ foldA: {
1096
+ const construct = x.makeStruct(schema)
1097
+
1098
+ /* ensure that schema/construct/struct/~standard subject types are identical */
1099
+
1100
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
1101
+
1102
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
1103
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
1104
+
1105
+ type SchemaSubj = x.Infer<typeof schema>
1106
+
1107
+ x.tCh<SchemaSubj, ExpectedSubj>()
1108
+ x.tCh<ExpectedSubj, SchemaSubj>()
1109
+
1110
+ type StructSubj = x.Infer<typeof struct.__schema>
1111
+
1112
+ x.tCh<StructSubj, ExpectedSubj>()
1113
+ x.tCh<ExpectedSubj, StructSubj>()
1114
+
1115
+ type StandardSubj = NonNullable<
1116
+ (typeof struct)['~standard']['types']
1117
+ >['output']
1118
+
1119
+ x.tCh<StandardSubj, ExpectedSubj>()
1120
+ x.tCh<ExpectedSubj, StandardSubj>()
1121
+
1122
+ /* parsed either type check */
1123
+
1124
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
1125
+
1126
+ const parsed = x.parse(schema, undefined)
1127
+
1128
+ type SchemaParsed = typeof parsed
1129
+
1130
+ x.tCh<SchemaParsed, ExpectedParsed>()
1131
+ x.tCh<ExpectedParsed, SchemaParsed>()
1132
+
1133
+ type ConstructParsed = ReturnType<typeof construct.parse>
1134
+
1135
+ x.tCh<ConstructParsed, ExpectedParsed>()
1136
+ x.tCh<ExpectedParsed, ConstructParsed>()
1137
+
1138
+ type StructParsed = ReturnType<typeof struct.parse>
1139
+
1140
+ x.tCh<StructParsed, ExpectedParsed>()
1141
+ x.tCh<ExpectedParsed, StructParsed>()
1142
+
1143
+ type StandardParsed = Extract<
1144
+ ReturnType<(typeof struct)['~standard']['validate']>,
1145
+ { value: unknown }
1146
+ >['value']
1147
+
1148
+ x.tCh<StandardParsed, ExpectedSubj>()
1149
+ x.tCh<ExpectedSubj, StandardParsed>()
1150
+
1151
+ /* runtime schema check */
1152
+
1153
+ expect(struct.__schema).toStrictEqual(schema)
1154
+ expect(construct.__schema).toStrictEqual(schema)
1155
+ expect(construct.__schema === schema).toBe(false)
1156
+
1157
+ /* parse result check */
1158
+
1159
+ for (const subj of subjects) {
1160
+ const schemaParsed = x.parse(schema, subj)
1161
+
1162
+ expect(schemaParsed.error).toBe(undefined)
1163
+ expect(schemaParsed.data).toStrictEqual(subj)
1164
+
1165
+ const constructParsed = construct.parse(subj)
1166
+
1167
+ expect(constructParsed.error).toBe(undefined)
1168
+ expect(constructParsed.data).toStrictEqual(subj)
1169
+
1170
+ const structParsed = struct.parse(subj)
1171
+
1172
+ expect(structParsed.error).toBe(undefined)
1173
+ expect(structParsed.data).toStrictEqual(subj)
1174
+
1175
+ const standardParsed = struct['~standard'].validate(subj)
1176
+
1177
+ if (standardParsed instanceof Promise) {
1178
+ throw Error('Not expected')
1179
+ }
1180
+
1181
+ if (standardParsed.issues !== undefined) {
1182
+ throw Error('not expected')
1183
+ }
1184
+
1185
+ expect(standardParsed.value).toStrictEqual(subj)
1186
+ }
1187
+ }
1188
+ })
1189
+
1190
+ it('each schema type as nested schema', () => {
1191
+ const schema = {
1192
+ type: 'tuple',
1193
+ of: [
1194
+ { type: 'boolean' },
1195
+ { type: 'literal', of: true },
1196
+ { type: 'literal', of: 0 },
1197
+ { type: 'number' },
1198
+ { type: 'string' },
1199
+ //
1200
+ { type: 'array', of: { type: 'boolean' } },
1201
+ { type: 'object', of: { x: { type: 'boolean' } } },
1202
+ { type: 'record', of: { type: 'boolean' } },
1203
+ { type: 'union', of: [{ type: 'boolean' }] },
1204
+ ],
1205
+ } as const satisfies x.Schema
1206
+
1207
+ const struct = x.tuple([
1208
+ x.boolean(),
1209
+ x.literal(true),
1210
+ x.literal(0),
1211
+ x.number(),
1212
+ x.string(),
1213
+ //
1214
+ x.array(x.boolean()),
1215
+ x.object({ x: x.boolean() }),
1216
+ x.record(x.boolean()),
1217
+ x.union([x.boolean()]),
1218
+ ])
1219
+
1220
+ type ExpectedSubj = [
1221
+ boolean,
1222
+ true,
1223
+ 0,
1224
+ number,
1225
+ string,
1226
+ boolean[],
1227
+ { x: boolean },
1228
+ Record<string, boolean>,
1229
+ boolean,
1230
+ ]
1231
+
1232
+ const subjects: Array<ExpectedSubj> = [
1233
+ [
1234
+ false,
1235
+ true,
1236
+ 0,
1237
+ 69,
1238
+ 'x',
1239
+ //
1240
+ [true, false],
1241
+ { x: true },
1242
+ { x: true },
1243
+ false,
1244
+ ],
1245
+ ]
1246
+
1247
+ foldA: {
1248
+ const construct = x.makeStruct(schema)
1249
+
1250
+ /* ensure that schema/construct/struct/~standard subject types are identical */
1251
+
1252
+ type ConstructSchemaSubj = x.Infer<typeof construct.__schema>
1253
+
1254
+ x.tCh<ConstructSchemaSubj, ExpectedSubj>()
1255
+ x.tCh<ExpectedSubj, ConstructSchemaSubj>()
1256
+
1257
+ type SchemaSubj = x.Infer<typeof schema>
1258
+
1259
+ x.tCh<SchemaSubj, ExpectedSubj>()
1260
+ x.tCh<ExpectedSubj, SchemaSubj>()
1261
+
1262
+ type StructSubj = x.Infer<typeof struct.__schema>
1263
+
1264
+ x.tCh<StructSubj, ExpectedSubj>()
1265
+ x.tCh<ExpectedSubj, StructSubj>()
1266
+
1267
+ type StandardSubj = NonNullable<
1268
+ (typeof struct)['~standard']['types']
1269
+ >['output']
1270
+
1271
+ x.tCh<StandardSubj, ExpectedSubj>()
1272
+ x.tCh<ExpectedSubj, StandardSubj>()
1273
+
1274
+ /* parsed either type check */
1275
+
1276
+ type ExpectedParsed = x.ParseResult<ExpectedSubj>
1277
+
1278
+ const parsed = x.parse(schema, undefined)
1279
+
1280
+ type SchemaParsed = typeof parsed
1281
+
1282
+ x.tCh<SchemaParsed, ExpectedParsed>()
1283
+ x.tCh<ExpectedParsed, SchemaParsed>()
1284
+
1285
+ type ConstructParsed = ReturnType<typeof construct.parse>
1286
+
1287
+ x.tCh<ConstructParsed, ExpectedParsed>()
1288
+ x.tCh<ExpectedParsed, ConstructParsed>()
1289
+
1290
+ type StructParsed = ReturnType<typeof struct.parse>
1291
+
1292
+ x.tCh<StructParsed, ExpectedParsed>()
1293
+ x.tCh<ExpectedParsed, StructParsed>()
1294
+
1295
+ type StandardParsed = Extract<
1296
+ ReturnType<(typeof struct)['~standard']['validate']>,
1297
+ { value: unknown }
1298
+ >['value']
1299
+
1300
+ x.tCh<StandardParsed, ExpectedSubj>()
1301
+ x.tCh<ExpectedSubj, StandardParsed>()
1302
+
1303
+ /* runtime schema check */
1304
+
1305
+ expect(struct.__schema).toStrictEqual(schema)
1306
+ expect(construct.__schema).toStrictEqual(schema)
1307
+ expect(construct.__schema === schema).toBe(false)
1308
+
1309
+ /* parse result check */
1310
+
1311
+ for (const subj of subjects) {
1312
+ const schemaParsed = x.parse(schema, subj)
1313
+
1314
+ expect(schemaParsed.error).toBe(undefined)
1315
+ expect(schemaParsed.data).toStrictEqual(subj)
1316
+
1317
+ const constructParsed = construct.parse(subj)
1318
+
1319
+ expect(constructParsed.error).toBe(undefined)
1320
+ expect(constructParsed.data).toStrictEqual(subj)
1321
+
1322
+ const structParsed = struct.parse(subj)
1323
+
1324
+ expect(structParsed.error).toBe(undefined)
1325
+ expect(structParsed.data).toStrictEqual(subj)
1326
+
1327
+ const standardParsed = struct['~standard'].validate(subj)
1328
+
1329
+ if (standardParsed instanceof Promise) {
1330
+ throw Error('Not expected')
1331
+ }
1332
+
1333
+ if (standardParsed.issues !== undefined) {
1334
+ throw Error('not expected')
1335
+ }
1336
+
1337
+ expect(standardParsed.value).toStrictEqual(subj)
1338
+ }
1339
+ }
1340
+ })
1341
+ })