@sinclair/typebox 0.29.0 → 0.29.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.29.0",
3
+ "version": "0.29.2",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",
package/readme.md CHANGED
@@ -888,14 +888,16 @@ const C = Type.Index(T, Type.KeyOf(T)) // const C = {
888
888
 
889
889
  ### Not Types
890
890
 
891
- Not types are supported with `Type.Not`. This type represents the JSON Schema `not` keyword and will statically infer as `unknown`. Note that negated (or not) types are not supported in TypeScript, but can still be partially expressed by interpreting `not` as the broad type `unknown`. When used with intersect types, the Not type can create refined assertion rules for types by leveraging TypeScript's ability to narrow from `unknown` to an intended type through intersection.
892
-
893
- For example, consider a type which is `number` but not `1 | 2 | 3` and where the static type would still technically be a `number`. The following shows a pseudo TypeScript example using `not` followed by the TypeBox implementation.
891
+ TypeBox has partial support for the JSON schema `not` keyword with `Type.Not`. This type is synonymous with the concept of a [negated types](https://github.com/microsoft/TypeScript/issues/4196) which are not supported in the TypeScript language. TypeBox does provide partial inference support via the intersection of `T & not U` (where all negated types infer as `unknown`). This can be used in the following context.
894
892
 
895
893
  ```typescript
896
- // Pseudo TypeScript
894
+ // TypeScript
897
895
 
898
- type T = number & not (1 | 2 | 3) // allow all numbers except 1, 2, 3
896
+ type T = Exclude<number, 1 | 2 | 3> // all numbers except 1, 2, 3
897
+ //
898
+ // ideally expressed as:
899
+ //
900
+ // type T = number & not (1 | 2 | 3)
899
901
 
900
902
  // TypeBox
901
903
 
@@ -914,11 +916,11 @@ const T = Type.Intersect([ // const T = {
914
916
  // ]
915
917
  // }
916
918
 
917
- type T = Static<typeof T> // evaluates as:
919
+ type T = Static<typeof T> // inferred:
918
920
  //
919
- // type T = (number & (not (1 | 2 | 3)))
920
- // type T = (number & (unknown))
921
- // type T = (number)
921
+ // type T = number & not (1 | 2 | 3)
922
+ // type T = number & unknown
923
+ // type T = number
922
924
  ```
923
925
 
924
926
  The Not type can be used with constraints to define schematics for types that would otherwise be difficult to express.
@@ -1473,6 +1475,7 @@ The following is a list of community packages that provide general tooling and f
1473
1475
  | [fetch-typebox](https://github.com/erfanium/fetch-typebox) | Drop-in replacement for fetch that brings easy integration with TypeBox |
1474
1476
  | [schema2typebox](https://github.com/xddq/schema2typebox) | Creating TypeBox code from JSON schemas |
1475
1477
  | [ts2typebox](https://github.com/xddq/ts2typebox) | Creating TypeBox code from Typescript types |
1478
+ | [typebox-client](https://github.com/flodlc/typebox-client) | Type safe http client library for Fastify |
1476
1479
  | [typebox-validators](https://github.com/jtlapp/typebox-validators) | Advanced validators supporting discriminated and heterogeneous unions |
1477
1480
 
1478
1481
  <a name='benchmark'></a>
@@ -1493,35 +1496,35 @@ This benchmark measures compilation performance for varying types. You can revie
1493
1496
  ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
1494
1497
  │ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
1495
1498
  ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
1496
- │ Literal_String │ 1000 │ ' 220 ms' │ ' 6 ms' │ ' 36.67 x' │
1497
- │ Literal_Number │ 1000 │ ' 172 ms' │ ' 4 ms' │ ' 43.00 x' │
1498
- │ Literal_Boolean │ 1000 │ ' 162 ms' │ ' 4 ms' │ ' 40.50 x' │
1499
+ │ Literal_String │ 1000 │ ' 227 ms' │ ' 7 ms' │ ' 32.43 x' │
1500
+ │ Literal_Number │ 1000 │ ' 180 ms' │ ' 6 ms' │ ' 30.00 x' │
1501
+ │ Literal_Boolean │ 1000 │ ' 152 ms' │ ' 5 ms' │ ' 30.40 x' │
1499
1502
  │ Primitive_Number │ 1000 │ ' 161 ms' │ ' 6 ms' │ ' 26.83 x' │
1500
- │ Primitive_String │ 1000 │ ' 154 ms' │ ' 4 ms' │ ' 38.50 x' │
1501
- │ Primitive_String_Pattern │ 1000 │ ' 204 ms' │ ' 10 ms' │ ' 20.40 x' │
1502
- │ Primitive_Boolean │ 1000 │ ' 131 ms' │ ' 4 ms' │ ' 32.75 x' │
1503
- │ Primitive_Null │ 1000 │ ' 142 ms' │ ' 5 ms' │ ' 28.40 x' │
1504
- │ Object_Unconstrained │ 1000 │ ' 1263 ms' │ ' 29 ms' │ ' 43.55 x' │
1505
- │ Object_Constrained │ 1000 │ ' 1267 ms' │ ' 24 ms' │ ' 52.79 x' │
1506
- │ Object_Vector3 │ 1000 │ ' 382 ms' │ ' 7 ms' │ ' 54.57 x' │
1507
- │ Object_Box3D │ 1000 │ ' 1723 ms' │ ' 28 ms' │ ' 61.54 x' │
1508
- │ Tuple_Primitive │ 1000 │ ' 495 ms' │ ' 13 ms' │ ' 38.08 x' │
1509
- │ Tuple_Object │ 1000 │ ' 1271 ms' │ ' 16 ms' │ ' 79.44 x' │
1510
- │ Composite_Intersect │ 1000 │ ' 656 ms' │ ' 19 ms' │ ' 34.53 x' │
1511
- │ Composite_Union │ 1000 │ ' 529 ms' │ ' 18 ms' │ ' 29.39 x' │
1512
- │ Math_Vector4 │ 1000 │ ' 802 ms' │ ' 14 ms' │ ' 57.29 x' │
1513
- │ Math_Matrix4 │ 1000 │ ' 411 ms' │ ' 6 ms' │ ' 68.50 x' │
1514
- │ Array_Primitive_Number │ 1000 │ ' 369 ms' │ ' 6 ms' │ ' 61.50 x' │
1515
- │ Array_Primitive_String │ 1000 │ ' 369 ms' │ ' 4 ms' │ ' 92.25 x' │
1516
- │ Array_Primitive_Boolean │ 1000 │ ' 297 ms' │ ' 3 ms' │ ' 99.00 x' │
1517
- │ Array_Object_Unconstrained │ 1000 │ ' 1582 ms' │ ' 20 ms' │ ' 79.10 x' │
1518
- │ Array_Object_Constrained │ 1000 │ ' 1629 ms' │ ' 19 ms' │ ' 85.74 x' │
1519
- │ Array_Tuple_Primitive │ 1000 │ ' 652 ms' │ ' 12 ms' │ ' 54.33 x' │
1520
- │ Array_Tuple_Object │ 1000 │ ' 1587 ms' │ ' 16 ms' │ ' 99.19 x' │
1521
- │ Array_Composite_Intersect │ 1000 │ ' 1051 ms' │ ' 15 ms' │ ' 70.07 x' │
1522
- │ Array_Composite_Union │ 1000 │ ' 733 ms' │ ' 15 ms' │ ' 48.87 x' │
1523
- │ Array_Math_Vector4 │ 1000 │ ' 1071 ms' │ ' 12 ms' │ ' 89.25 x' │
1524
- │ Array_Math_Matrix4 │ 1000 │ ' 636 ms' │ ' 5 ms' │ ' 127.20 x' │
1503
+ │ Primitive_String │ 1000 │ ' 150 ms' │ ' 8 ms' │ ' 18.75 x' │
1504
+ │ Primitive_String_Pattern │ 1000 │ ' 202 ms' │ ' 9 ms' │ ' 22.44 x' │
1505
+ │ Primitive_Boolean │ 1000 │ ' 133 ms' │ ' 3 ms' │ ' 44.33 x' │
1506
+ │ Primitive_Null │ 1000 │ ' 147 ms' │ ' 3 ms' │ ' 49.00 x' │
1507
+ │ Object_Unconstrained │ 1000 │ ' 1145 ms' │ ' 31 ms' │ ' 36.94 x' │
1508
+ │ Object_Constrained │ 1000 │ ' 1241 ms' │ ' 26 ms' │ ' 47.73 x' │
1509
+ │ Object_Vector3 │ 1000 │ ' 407 ms' │ ' 7 ms' │ ' 58.14 x' │
1510
+ │ Object_Box3D │ 1000 │ ' 1781 ms' │ ' 27 ms' │ ' 65.96 x' │
1511
+ │ Tuple_Primitive │ 1000 │ ' 489 ms' │ ' 13 ms' │ ' 37.62 x' │
1512
+ │ Tuple_Object │ 1000 │ ' 1278 ms' │ ' 34 ms' │ ' 37.59 x' │
1513
+ │ Composite_Intersect │ 1000 │ ' 613 ms' │ ' 16 ms' │ ' 38.31 x' │
1514
+ │ Composite_Union │ 1000 │ ' 543 ms' │ ' 18 ms' │ ' 30.17 x' │
1515
+ │ Math_Vector4 │ 1000 │ ' 819 ms' │ ' 13 ms' │ ' 63.00 x' │
1516
+ │ Math_Matrix4 │ 1000 │ ' 407 ms' │ ' 7 ms' │ ' 58.14 x' │
1517
+ │ Array_Primitive_Number │ 1000 │ ' 372 ms' │ ' 6 ms' │ ' 62.00 x' │
1518
+ │ Array_Primitive_String │ 1000 │ ' 329 ms' │ ' 6 ms' │ ' 54.83 x' │
1519
+ │ Array_Primitive_Boolean │ 1000 │ ' 313 ms' │ ' 3 ms' │ ' 104.33 x' │
1520
+ │ Array_Object_Unconstrained │ 1000 │ ' 1780 ms' │ ' 20 ms' │ ' 89.00 x' │
1521
+ │ Array_Object_Constrained │ 1000 │ ' 1494 ms' │ ' 21 ms' │ ' 71.14 x' │
1522
+ │ Array_Tuple_Primitive │ 1000 │ ' 917 ms' │ ' 10 ms' │ ' 91.70 x' │
1523
+ │ Array_Tuple_Object │ 1000 │ ' 1666 ms' │ ' 13 ms' │ ' 128.15 x' │
1524
+ │ Array_Composite_Intersect │ 1000 │ ' 791 ms' │ ' 18 ms' │ ' 43.94 x' │
1525
+ │ Array_Composite_Union │ 1000 │ ' 833 ms' │ ' 17 ms' │ ' 49.00 x' │
1526
+ │ Array_Math_Vector4 │ 1000 │ ' 1161 ms' │ ' 15 ms' │ ' 77.40 x' │
1527
+ │ Array_Math_Matrix4 │ 1000 │ ' 697 ms' │ ' 10 ms' │ ' 69.70 x' │
1525
1528
  └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
1526
1529
  ```
1527
1530
 
@@ -1535,37 +1538,37 @@ This benchmark measures validation performance for varying types. You can review
1535
1538
  ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
1536
1539
  │ (index) │ Iterations │ ValueCheck │ Ajv │ TypeCompiler │ Performance │
1537
1540
  ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
1538
- │ Literal_String │ 1000000 │ ' 24 ms' │ ' 5 ms' │ ' 5 ms' │ ' 1.00 x' │
1539
- │ Literal_Number │ 1000000 │ ' 21 ms' │ ' 17 ms' │ ' 9 ms' │ ' 1.89 x' │
1541
+ │ Literal_String │ 1000000 │ ' 25 ms' │ ' 5 ms' │ ' 4 ms' │ ' 1.25 x' │
1542
+ │ Literal_Number │ 1000000 │ ' 19 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1540
1543
  │ Literal_Boolean │ 1000000 │ ' 18 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1541
- │ Primitive_Number │ 1000000 │ ' 25 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1542
- │ Primitive_String │ 1000000 │ ' 25 ms' │ ' 17 ms' │ ' 9 ms' │ ' 1.89 x' │
1543
- │ Primitive_String_Pattern │ 1000000 │ ' 174 ms' │ ' 44 ms' │ ' 36 ms' │ ' 1.22 x' │
1544
- │ Primitive_Boolean │ 1000000 │ ' 22 ms' │ ' 17 ms' │ ' 9 ms' │ ' 1.89 x' │
1545
- │ Primitive_Null │ 1000000 │ ' 22 ms' │ ' 16 ms' │ ' 9 ms' │ ' 1.78 x' │
1546
- │ Object_Unconstrained │ 1000000 │ ' 1065 ms' │ ' 33 ms' │ ' 25 ms' │ ' 1.32 x' │
1547
- │ Object_Constrained │ 1000000 │ ' 1192 ms' │ ' 53 ms' │ ' 38 ms' │ ' 1.39 x' │
1548
- │ Object_Vector3 │ 1000000 │ ' 410 ms' │ ' 23 ms' │ ' 14 ms' │ ' 1.64 x' │
1549
- │ Object_Box3D │ 1000000 │ ' 1939 ms' │ ' 54 ms' │ ' 50 ms' │ ' 1.08 x' │
1550
- │ Object_Recursive │ 1000000 │ ' 5248 ms' │ ' 355 ms' │ ' 149 ms' │ ' 2.38 x' │
1551
- │ Tuple_Primitive │ 1000000 │ ' 163 ms' │ ' 21 ms' │ ' 13 ms' │ ' 1.62 x' │
1552
- │ Tuple_Object │ 1000000 │ ' 737 ms' │ ' 29 ms' │ ' 20 ms' │ ' 1.45 x' │
1553
- │ Composite_Intersect │ 1000000 │ ' 761 ms' │ ' 24 ms' │ ' 15 ms' │ ' 1.60 x' │
1554
- │ Composite_Union │ 1000000 │ ' 519 ms' │ ' 23 ms' │ ' 13 ms' │ ' 1.77 x' │
1555
- │ Math_Vector4 │ 1000000 │ ' 247 ms' │ ' 21 ms' │ ' 11 ms' │ ' 1.91 x' │
1556
- │ Math_Matrix4 │ 1000000 │ ' 1045 ms' │ ' 39 ms' │ ' 27 ms' │ ' 1.44 x' │
1557
- │ Array_Primitive_Number │ 1000000 │ ' 256 ms' │ ' 20 ms' │ ' 12 ms' │ ' 1.67 x' │
1558
- │ Array_Primitive_String │ 1000000 │ ' 222 ms' │ ' 21 ms' │ ' 14 ms' │ ' 1.50 x' │
1559
- │ Array_Primitive_Boolean │ 1000000 │ ' 149 ms' │ ' 22 ms' │ ' 16 ms' │ ' 1.38 x' │
1560
- │ Array_Object_Unconstrained │ 1000000 │ ' 5473 ms' │ ' 67 ms' │ ' 59 ms' │ ' 1.14 x' │
1561
- │ Array_Object_Constrained │ 1000000 │ ' 5548 ms' │ ' 130 ms' │ ' 116 ms' │ ' 1.12 x' │
1562
- │ Array_Object_Recursive │ 1000000 │ ' 21047 ms' │ ' 1710 ms' │ ' 584 ms' │ ' 2.93 x' │
1563
- │ Array_Tuple_Primitive │ 1000000 │ ' 691 ms' │ ' 35 ms' │ ' 29 ms' │ ' 1.21 x' │
1564
- │ Array_Tuple_Object │ 1000000 │ ' 3075 ms' │ ' 63 ms' │ ' 50 ms' │ ' 1.26 x' │
1565
- │ Array_Composite_Intersect │ 1000000 │ ' 3126 ms' │ ' 44 ms' │ ' 35 ms' │ ' 1.26 x' │
1566
- │ Array_Composite_Union │ 1000000 │ ' 2086 ms' │ ' 68 ms' │ ' 33 ms' │ ' 2.06 x' │
1567
- │ Array_Math_Vector4 │ 1000000 │ ' 1069 ms' │ ' 38 ms' │ ' 23 ms' │ ' 1.65 x' │
1568
- │ Array_Math_Matrix4 │ 1000000 │ ' 4559 ms' │ ' 111 ms' │ ' 88 ms' │ ' 1.26 x' │
1544
+ │ Primitive_Number │ 1000000 │ ' 26 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1545
+ │ Primitive_String │ 1000000 │ ' 25 ms' │ ' 19 ms' │ ' 10 ms' │ ' 1.90 x' │
1546
+ │ Primitive_String_Pattern │ 1000000 │ ' 160 ms' │ ' 42 ms' │ ' 36 ms' │ ' 1.17 x' │
1547
+ │ Primitive_Boolean │ 1000000 │ ' 24 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1548
+ │ Primitive_Null │ 1000000 │ ' 24 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │
1549
+ │ Object_Unconstrained │ 1000000 │ ' 1111 ms' │ ' 34 ms' │ ' 24 ms' │ ' 1.42 x' │
1550
+ │ Object_Constrained │ 1000000 │ ' 1262 ms' │ ' 51 ms' │ ' 37 ms' │ ' 1.38 x' │
1551
+ │ Object_Vector3 │ 1000000 │ ' 445 ms' │ ' 23 ms' │ ' 13 ms' │ ' 1.77 x' │
1552
+ │ Object_Box3D │ 1000000 │ ' 2029 ms' │ ' 66 ms' │ ' 48 ms' │ ' 1.38 x' │
1553
+ │ Object_Recursive │ 1000000 │ ' 5121 ms' │ ' 464 ms' │ ' 156 ms' │ ' 2.97 x' │
1554
+ │ Tuple_Primitive │ 1000000 │ ' 158 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │
1555
+ │ Tuple_Object │ 1000000 │ ' 761 ms' │ ' 30 ms' │ ' 18 ms' │ ' 1.67 x' │
1556
+ │ Composite_Intersect │ 1000000 │ ' 828 ms' │ ' 24 ms' │ ' 13 ms' │ ' 1.85 x' │
1557
+ │ Composite_Union │ 1000000 │ ' 529 ms' │ ' 22 ms' │ ' 13 ms' │ ' 1.69 x' │
1558
+ │ Math_Vector4 │ 1000000 │ ' 252 ms' │ ' 22 ms' │ ' 11 ms' │ ' 2.00 x' │
1559
+ │ Math_Matrix4 │ 1000000 │ ' 1024 ms' │ ' 38 ms' │ ' 27 ms' │ ' 1.41 x' │
1560
+ │ Array_Primitive_Number │ 1000000 │ ' 264 ms' │ ' 22 ms' │ ' 11 ms' │ ' 2.00 x' │
1561
+ │ Array_Primitive_String │ 1000000 │ ' 240 ms' │ ' 20 ms' │ ' 13 ms' │ ' 1.54 x' │
1562
+ │ Array_Primitive_Boolean │ 1000000 │ ' 137 ms' │ ' 21 ms' │ ' 13 ms' │ ' 1.62 x' │
1563
+ │ Array_Object_Unconstrained │ 1000000 │ ' 6050 ms' │ ' 66 ms' │ ' 55 ms' │ ' 1.20 x' │
1564
+ │ Array_Object_Constrained │ 1000000 │ ' 5954 ms' │ ' 124 ms' │ ' 116 ms' │ ' 1.07 x' │
1565
+ │ Array_Object_Recursive │ 1000000 │ ' 21074 ms' │ ' 1611 ms' │ ' 626 ms' │ ' 2.57 x' │
1566
+ │ Array_Tuple_Primitive │ 1000000 │ ' 683 ms' │ ' 37 ms' │ ' 30 ms' │ ' 1.23 x' │
1567
+ │ Array_Tuple_Object │ 1000000 │ ' 3366 ms' │ ' 69 ms' │ ' 54 ms' │ ' 1.28 x' │
1568
+ │ Array_Composite_Intersect │ 1000000 │ ' 3285 ms' │ ' 45 ms' │ ' 36 ms' │ ' 1.25 x' │
1569
+ │ Array_Composite_Union │ 1000000 │ ' 2229 ms' │ ' 69 ms' │ ' 34 ms' │ ' 2.03 x' │
1570
+ │ Array_Math_Vector4 │ 1000000 │ ' 1192 ms' │ ' 38 ms' │ ' 25 ms' │ ' 1.52 x' │
1571
+ │ Array_Math_Matrix4 │ 1000000 │ ' 4916 ms' │ ' 111 ms' │ ' 88 ms' │ ' 1.26 x' │
1569
1572
  └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
1570
1573
  ```
1571
1574
 
@@ -1579,11 +1582,11 @@ The following table lists esbuild compiled and minified sizes for each TypeBox m
1579
1582
  ┌──────────────────────┬────────────┬────────────┬─────────────┐
1580
1583
  │ (index) │ Compiled │ Minified │ Compression │
1581
1584
  ├──────────────────────┼────────────┼────────────┼─────────────┤
1582
- │ typebox/compiler │ '128.0 kb' │ ' 57.0 kb' │ '2.25 x' │
1583
- │ typebox/errors │ '111.6 kb' │ ' 49.1 kb' │ '2.27 x' │
1584
- │ typebox/system │ ' 77.0 kb' │ ' 31.5 kb' │ '2.45 x' │
1585
- │ typebox/value │ '177.7 kb' │ ' 76.8 kb' │ '2.31 x' │
1586
- │ typebox │ ' 75.9 kb' │ ' 31.0 kb' │ '2.45 x' │
1585
+ │ typebox/compiler │ '130.3 kb' │ ' 58.2 kb' │ '2.24 x' │
1586
+ │ typebox/errors │ '113.3 kb' │ ' 49.8 kb' │ '2.27 x' │
1587
+ │ typebox/system │ ' 78.8 kb' │ ' 32.2 kb' │ '2.45 x' │
1588
+ │ typebox/value │ '180.0 kb' │ ' 77.7 kb' │ '2.32 x' │
1589
+ │ typebox │ ' 77.7 kb' │ ' 31.7 kb' │ '2.45 x' │
1587
1590
  └──────────────────────┴────────────┴────────────┴─────────────┘
1588
1591
  ```
1589
1592
 
package/typebox.d.ts CHANGED
@@ -25,8 +25,6 @@ export type Ensure<T> = T extends infer U ? U : never;
25
25
  export type AssertProperties<T> = T extends TProperties ? T : TProperties;
26
26
  export type AssertRest<T, E extends TSchema[] = TSchema[]> = T extends E ? T : [];
27
27
  export type AssertType<T, E extends TSchema = TSchema> = T extends E ? T : TNever;
28
- export type IntersectType<T extends TSchema[]> = T extends [] ? TNever : T extends [TSchema] ? AssertType<T[0]> : TIntersect<T>;
29
- export type UnionType<T extends TSchema[]> = T extends [] ? TNever : T extends [TSchema] ? AssertType<T[0]> : TUnion<T>;
30
28
  export type TModifier = TReadonlyOptional<TSchema> | TOptional<TSchema> | TReadonly<TSchema>;
31
29
  export type TReadonly<T extends TSchema> = T & {
32
30
  [Modifier]: 'Readonly';
@@ -37,6 +35,14 @@ export type TOptional<T extends TSchema> = T & {
37
35
  export type TReadonlyOptional<T extends TSchema> = T & {
38
36
  [Modifier]: 'ReadonlyOptional';
39
37
  };
38
+ export type OptionalUnwrapType<T extends TSchema> = T extends (TOptional<infer S> | TReadonlyOptional<infer S>) ? OptionalUnwrapType<S> : T;
39
+ export type OptionalUnwrapRest<T extends TSchema[]> = T extends [infer L, ...infer R] ? L extends (TOptional<infer S> | TReadonlyOptional<infer S>) ? [OptionalUnwrapType<AssertType<S>>, ...OptionalUnwrapRest<AssertRest<R>>] : [L, ...OptionalUnwrapRest<AssertRest<R>>] : [];
40
+ export type IntersectOptional<T extends TSchema[]> = T extends [infer L, ...infer R] ? L extends TOptional<AssertType<L>> | TReadonlyOptional<AssertType<L>> ? IntersectOptional<AssertRest<R>> : false : true;
41
+ export type IntersectResolve<T extends TSchema[], U = OptionalUnwrapRest<AssertRest<T>>> = IntersectOptional<AssertRest<T>> extends true ? TOptional<TIntersect<AssertRest<U>>> : TIntersect<AssertRest<U>>;
42
+ export type IntersectType<T extends TSchema[]> = T extends [] ? TNever : T extends [TSchema] ? AssertType<T[0]> : IntersectResolve<T>;
43
+ export type UnionOptional<T extends TSchema[]> = T extends [infer L, ...infer R] ? L extends (TOptional<AssertType<L>> | TReadonlyOptional<AssertType<L>>) ? true : UnionOptional<AssertRest<R>> : false;
44
+ export type UnionResolve<T extends TSchema[], U = OptionalUnwrapRest<AssertRest<T>>> = UnionOptional<AssertRest<T>> extends true ? TOptional<TUnion<AssertRest<U>>> : TUnion<AssertRest<U>>;
45
+ export type UnionType<T extends TSchema[]> = T extends [] ? TNever : T extends [TSchema] ? AssertType<T[0]> : UnionResolve<T>;
40
46
  export type Key = string | number;
41
47
  export interface SchemaOptions {
42
48
  $schema?: string;
package/typebox.js CHANGED
@@ -887,7 +887,7 @@ var TypeExtends;
887
887
  // --------------------------------------------------------------------------
888
888
  // Not
889
889
  // --------------------------------------------------------------------------
890
- function ResolveNot(schema) {
890
+ function UnwrapNot(schema) {
891
891
  let [current, depth] = [schema, 0];
892
892
  while (true) {
893
893
  if (!TypeGuard.TNot(current))
@@ -897,6 +897,16 @@ var TypeExtends;
897
897
  }
898
898
  return depth % 2 === 0 ? current : exports.Type.Unknown();
899
899
  }
900
+ function Not(left, right) {
901
+ // TypeScript has no concept of negated types, and attempts to correctly check the negated
902
+ // type at runtime would put TypeBox at odds with TypeScripts ability to statically infer
903
+ // the type. Instead we unwrap to either unknown or T and continue evaluating.
904
+ if (TypeGuard.TNot(left))
905
+ return Visit(UnwrapNot(left), right);
906
+ if (TypeGuard.TNot(right))
907
+ return Visit(left, UnwrapNot(right));
908
+ throw new Error(`TypeExtends: Invalid fallthrough for Not`);
909
+ }
900
910
  // --------------------------------------------------------------------------
901
911
  // Null
902
912
  // --------------------------------------------------------------------------
@@ -1182,6 +1192,19 @@ var TypeExtends;
1182
1192
  return TypeGuard.TSymbol(right) ? TypeExtendsResult.True : TypeExtendsResult.False;
1183
1193
  }
1184
1194
  // --------------------------------------------------------------------------
1195
+ // TemplateLiteral
1196
+ // --------------------------------------------------------------------------
1197
+ function TemplateLiteral(left, right) {
1198
+ // TemplateLiteral types are resolved to either unions for finite expressions or string
1199
+ // for infinite expressions. Here we call to TemplateLiteralResolver to resolve for
1200
+ // either type and continue evaluating.
1201
+ if (TypeGuard.TTemplateLiteral(left))
1202
+ return Visit(TemplateLiteralResolver.Resolve(left), right);
1203
+ if (TypeGuard.TTemplateLiteral(right))
1204
+ return Visit(left, TemplateLiteralResolver.Resolve(right));
1205
+ throw new Error(`TypeExtends: Invalid fallthrough for TemplateLiteral`);
1206
+ }
1207
+ // --------------------------------------------------------------------------
1185
1208
  // Tuple
1186
1209
  // --------------------------------------------------------------------------
1187
1210
  function TupleRight(left, right) {
@@ -1317,17 +1340,12 @@ var TypeExtends;
1317
1340
  return TypeGuard.TVoid(right) ? TypeExtendsResult.True : TypeExtendsResult.False;
1318
1341
  }
1319
1342
  function Visit(left, right) {
1320
- // Not Unwrap
1321
- if (TypeGuard.TNot(left))
1322
- return Visit(ResolveNot(left), right);
1323
- if (TypeGuard.TNot(right))
1324
- return Visit(left, ResolveNot(right));
1325
- // Template Literal Union Unwrap
1326
- if (TypeGuard.TTemplateLiteral(left))
1327
- return Visit(TemplateLiteralResolver.Resolve(left), right);
1328
- if (TypeGuard.TTemplateLiteral(right))
1329
- return Visit(left, TemplateLiteralResolver.Resolve(right));
1330
- // Standard Extends
1343
+ // Resolvable Types
1344
+ if (TypeGuard.TTemplateLiteral(left) || TypeGuard.TTemplateLiteral(right))
1345
+ return TemplateLiteral(left, right);
1346
+ if (TypeGuard.TNot(left) || TypeGuard.TNot(right))
1347
+ return Not(left, right);
1348
+ // Standard Types
1331
1349
  if (TypeGuard.TAny(left))
1332
1350
  return Any(left, right);
1333
1351
  if (TypeGuard.TArray(left))
@@ -1425,16 +1443,43 @@ var TypeClone;
1425
1443
  // --------------------------------------------------------------------------
1426
1444
  var IndexedAccessor;
1427
1445
  (function (IndexedAccessor) {
1446
+ function OptionalUnwrap(schema) {
1447
+ return schema.map((schema) => {
1448
+ const { [exports.Modifier]: _, ...clone } = TypeClone.Clone(schema, {});
1449
+ return clone;
1450
+ });
1451
+ }
1452
+ function IsIntersectOptional(schema) {
1453
+ return schema.every((schema) => TypeGuard.TOptional(schema));
1454
+ }
1455
+ function IsUnionOptional(schema) {
1456
+ return schema.some((schema) => TypeGuard.TOptional(schema));
1457
+ }
1458
+ function ResolveIntersect(schema) {
1459
+ const optional = IsIntersectOptional(schema.allOf);
1460
+ return optional ? exports.Type.Optional(exports.Type.Intersect(OptionalUnwrap(schema.allOf))) : schema;
1461
+ }
1462
+ function ResolveUnion(schema) {
1463
+ const optional = IsUnionOptional(schema.anyOf);
1464
+ return optional ? exports.Type.Optional(exports.Type.Union(OptionalUnwrap(schema.anyOf))) : schema;
1465
+ }
1466
+ function ResolveOptional(schema) {
1467
+ if (schema[exports.Kind] === 'Intersect')
1468
+ return ResolveIntersect(schema);
1469
+ if (schema[exports.Kind] === 'Union')
1470
+ return ResolveUnion(schema);
1471
+ return schema;
1472
+ }
1428
1473
  function Intersect(schema, key) {
1429
- const schemas = schema.allOf.reduce((acc, schema) => {
1474
+ const resolved = schema.allOf.reduce((acc, schema) => {
1430
1475
  const indexed = Visit(schema, key);
1431
1476
  return indexed[exports.Kind] === 'Never' ? acc : [...acc, indexed];
1432
1477
  }, []);
1433
- return exports.Type.Intersect(schemas);
1478
+ return ResolveOptional(exports.Type.Intersect(resolved));
1434
1479
  }
1435
1480
  function Union(schema, key) {
1436
- const schemas = schema.anyOf.map((schema) => Visit(schema, key));
1437
- return exports.Type.Union(schemas);
1481
+ const resolved = schema.anyOf.map((schema) => Visit(schema, key));
1482
+ return ResolveOptional(exports.Type.Union(resolved));
1438
1483
  }
1439
1484
  function Object(schema, key) {
1440
1485
  const property = schema.properties[key];
@@ -1461,8 +1506,8 @@ var IndexedAccessor;
1461
1506
  return exports.Type.Never();
1462
1507
  }
1463
1508
  function Resolve(schema, keys, options = {}) {
1464
- // prettier-ignore
1465
- return exports.Type.Union(keys.map((key) => Visit(schema, key.toString())), options);
1509
+ const resolved = keys.map((key) => Visit(schema, key.toString()));
1510
+ return ResolveOptional(exports.Type.Union(resolved, options));
1466
1511
  }
1467
1512
  IndexedAccessor.Resolve = Resolve;
1468
1513
  })(IndexedAccessor || (exports.IndexedAccessor = IndexedAccessor = {}));