schematox 1.2.0 → 1.2.2-alpha

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