Skip to content

Commit 1504082

Browse files
committed
Revision 0.29.1
1 parent bdeb24f commit 1504082

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

changelog/0.29.0.md

+40-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ Revision 0.29.0 makes a minor interface and schema representation change to the
66

77
As this revision constitutes a breaking representation change for `Type.Not`, a minor semver revision is required.
88

9+
## Contents
10+
11+
- Enhancements
12+
- [Type.Not Representation Change](#Representation-Change)
13+
- [Not Inversion](#Not-Inversion)
14+
- [Inference Limitations](#Inference-Limitations)
15+
16+
<a name="Representation-Change"></a>
17+
918
## Type.Not Representation Change
1019

1120
The `Type.Not` was first introduced in Revision 0.26.0. This type accepted two arguments, the first is the `not` type, the second is the `allowed` type. In 0.26.0, TypeBox would treat the `allowed` type as the inferred type with the schema represented in the following form.
@@ -81,11 +90,13 @@ const T = {
8190
//
8291
type T = Static<typeof T> // type T = number
8392
```
84-
The 0.29.0 `Not` type properly represents the JSON Schema `not` keyword in its simplest form, as well as making better use of the type intersection narrowing capabilities of TypeScript with respect to inference.
93+
The 0.29.0 `Not` type properly represents the JSON Schema `not` keyword in its simplest form, as well as making better use of intersection type narrowing capabilities of TypeScript.
8594
86-
### Invert Not
95+
<a name="Not-Inversion"></a>
8796
88-
In revision 0.29.0, it is possible to invert the `Not` type. TypeBox will track each inversion and statically infer appropriately.
97+
## Not Inversion
98+
99+
The not type can be inverted through nesting.
89100
90101
```typescript
91102
// not not string
@@ -105,4 +116,29 @@ const T = {
105116
// inferred as
106117
//
107118
type T = Static<typeof T> // type T = string
108-
```
119+
```
120+
121+
<a name="Inference-Limitations"></a>
122+
123+
## Inference Limitations
124+
125+
Not types are synonymous with the concept of [negated types](https://github.com/microsoft/TypeScript/issues/4196) which are not supported in the TypeScript language. Because of this, it is not currently possible to infer negated types in a way one would naturally expect for some cases. Consider the following.
126+
127+
```typescript
128+
const T = Type.Intersect([Type.String(), Type.Not(Type.String())])
129+
130+
type T = Static<typeof T> // type T = string & not string
131+
// actual: string
132+
// expect: never
133+
```
134+
As such, the use of Not types should be used with some consideration to current limitations, and reserved primarily for narrowing cases such as the following.
135+
136+
```typescript
137+
const T = Type.Intersect([Type.String(), Type.Not(Type.Literal('disallowed string'))])
138+
139+
type T = Static<typeof T> // type T = string & not 'disallowed string'
140+
// actual: string
141+
// expect: string
142+
```
143+
144+

readme.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -888,14 +888,16 @@ const C = Type.Index(T, Type.KeyOf(T)) // const C = {
888888
889889
### Not Types
890890
891-
Not types are supported with `Type.Not`. This type represents the JSON Schema `not` keyword and will statically infer as `unknown`. Note that Not types are not supported in TypeScript, but can still be partially expressed by interpreting `not` as the broad type `unknown`. When used in intersections, the Not type can be used to create refined assertion rules for specific types, with the inference derived from TypeScript's ability to narrow from `unknown` to `T` via 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.
894892
895893
```typescript
896-
// Pseudo TypeScript
894+
// TypeScript
897895

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)
899901

900902
// TypeBox
901903

@@ -914,11 +916,11 @@ const T = Type.Intersect([ // const T = {
914916
// ]
915917
// }
916918

917-
type T = Static<typeof T> // evaluates as:
919+
type T = Static<typeof T> // inferred:
918920
//
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
922924
```
923925
924926
The Not type can be used with constraints to define schematics for types that would otherwise be difficult to express.

0 commit comments

Comments
 (0)