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