## [0.26.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.26.0)

## Overview

TypeBox now provides "runtime conditional types" (formally the `Conditional` module) as standard on `Type.*`. Additional updates in this revision include automatic union and intersection unwrap, universal support for utility types, several ergonomic enhancements and additional options for framework integrators. This revision also carries out a number an internal refactorings to reduce the amount of submodule imports.

Revision 0.26.0 is a milestone release for the TypeBox project and requires a minor semver update. 

## Contents

- Enhancements
  - [Standard Type Builder](#Standard-Type-Builder)
  - [Automatic Unwrap for Union and Intersect](#Automatic-Unwrap-for-Union-and-Intersect)
  - [Intersect and Union now Compose](#Intersect-and-Union-now-Compose)
  - [Runtime Conditional Types](#Runtime-Conditional-Types)
  - [Value Convert](#Value-Convert)
  - [Error Iterator](#Error-Iterator)
  - [Codegen without JIT](#Codegen-without-JIT)
  - [Standard Type (Composite)](#Standard-Type-Composite)
  - [Standard Type (Not)](#Standard-Type-Not)
  - [Extended Type (BigInt)](#Extended-Type-BigInt)
  - [Extended Type (Symbol)](#Extended-Type-Symbol)
- Breaking
  - [Minimum TypeScript Version](#Minimum-TypeScript-Version)
  - [Intersect Schema Representation](#Intersect-Schema-Representation)
  - [Never Schema Representation](#Never-Schema-Representation)
  - [Value Cast and Convert](#Value-Cast-and-Convert)
  - [Moved TypeGuard Module](#Moved-TypeGuard-Module)
  - [Format Renamed to FormatRegistry](#Format-Renamed-to-FormatRegistry)
  - [Custom Renamed to TypeRegistry](#Custom-Renamed-to-TypeRegistry)

<a name="Standard-Type-Builder"></a>

## Standard Type Builder

Revision 0.26.0 exports a new type builder called `StandardType`. This builder only allows for the construction JSON Schema compliant types by omitting all Extended types.
 
```typescript
import { StandardType as Type, Static } from '@sinclair/typebox'

const T = Type.Date() // error: no such function
```

<a name="Automatic-Unwrap-for-Union-and-Intersect"></a>

## Automatic Unwrap for Union and Intersect

Revision 0.26.0 will automatically unwrap unions and intersections for the following cases.

```typescript
const T1 = Type.Union([Type.String(), Type.Number()]) // TUnion<[TString, TNumber]>

const T2 = Type.Union([Type.String()])                // TString

const T3 = Type.Union([])                             // TNever
```

<a name="Intersect-and-Union-now-Compose"></a>

## Intersect and Union now Compose

Revision 0.26.0 re-enables support for union and intersection type composition. These types are also made compatible with `Pick`, `Omit`, `Partial`, `Required` and `KeyOf` utility types.

```typescript
const A = Type.Object({ type: Type.Literal('A') })
const B = Type.Object({ type: Type.Literal('B') })
const C = Type.Object({ type: Type.Literal('C') })

const Union = Type.Union([A, B, C])

const Extended = Type.Object({
  x: Type.Number(),
  y: Type.Number(),
  z: Type.Number()
})

const T = Type.Intersect([Union, Extended])          // type T = ({
                                                     //   type: "A";
                                                     //  } | {
                                                     //   type: "B";
                                                     // } | {
                                                     //   type: "C";
                                                     // }) & {
                                                     //   x: number;
                                                     //   y: number;
                                                     //   z: number;
                                                     // }

const K = Type.KeyOf(T)                              // type K = "type" | "x" | "y" | "z"

const P = Type.Pick(T, ['type', 'x'])                // type P = ({
                                                     //   type: "A";
                                                     // } | {
                                                     //   type: "B";
                                                     // } | {
                                                     //   type: "C";
                                                     // }) & {
                                                     //   x: number;
                                                     // }

const O = Type.Partial(P)                            // type O = ({
                                                     //   type?: "A" | undefined;
                                                     // } | {
                                                     //   type?: "B" | undefined;
                                                     // } | {
                                                     //   type?: "C" | undefined;
                                                     // }) & {
                                                     //   x?: number | undefined;
                                                     // }
```

<a name="Runtime-Conditional-Types"></a>

## Runtime Conditional Types

Revision 0.26.0 adds the runtime conditional types `Extends`, `Extract` and `Exclude` as standard. 

#### TypeScript

```typescript
type T0 = string extends number ? true : false                                                 
//   ^ false
type T1 = Extract<string | number, number>                                                     
//   ^ number
type T2 = Exclude<string | number, number>                                                     
//   ^ string
```

#### TypeBox
```typescript
const T0 = Type.Extends(Type.String(), Type.Number(), Type.Literal(true), Type.Literal(false)) 
//    ^ TLiteral<false>
const T1 = Type.Extract(Type.Union([Type.String(), Type.Number()]), Type.Number())             
//    ^ TNumber
const T2 = Type.Exclude(Type.Union([Type.String(), Type.Number()]), Type.Number())             
//    ^ TString<string>
```

<a name="Value-Convert"></a>

## Value Convert

Revision 0.26.0 adds a new `Convert` function to the `Value.*` module. This function will perform a type coercion for any value mismatched to its type if a reasonable conversion is possible.

```typescript
const T = Type.Number()

const A = Value.Convert(T, '42')                     // const A: unknown = 42 - ... Convert(...) will return `unknown`

const B = Value.Check(T, A)                          // const B = true        - ... so should be checked
```

<a name="Error-Iterator"></a>

## Error Iterator

Revision 0.26.0 now returns a `ValueErrorIterator` for `.Errors(...)`. This iterator provides a utility function to obtain the first error only. To obtain all errors, continue to use `for-of` enumeration or array spread syntax.

```typescript
const T = Type.Number()

const First = Value.Errors(T, 'foo').First()         // const First = { path: '', message: 'Expected number', ... }

const All = [...Value.Errors(T, 'foo')]              // const All = [{ path: '', message: 'Expected number', ... }]
```


<a name="Codegen-without-JIT"></a>

## Codegen without JIT

Revision 0.26.0 adds a `.Code()` function to the `TypeCompiler` to enable code generation without JIT evaluation.

```typescript
import { TypeCompiler } from '@sinclair/typebox/compiler'

const T = Type.Object({
  x: Type.Number(),
  y: Type.Number()
})

const C = TypeCompiler.Code(T)                       // return function check(value) {
                                                     //   return (
                                                     //    (typeof value === 'object' && value !== null) &&
                                                     //    !Array.isArray(value) &&
                                                     //    typeof value.x === 'number' &&
                                                     //    Number.isFinite(value.x) &&
                                                     //    typeof value.y === 'number' &&
                                                     //    Number.isFinite(value.y)
                                                     //   )
                                                     // }
```

<a name="Standard-Type-Not"></a>

## Standard Type (Not)

Revision 0.26.0 introduces the `Not` standard type. This type allows for the inversion of assertion logic which can be useful to narrow for broader types.

#### Example 1

```typescript
const T = Type.Not(Type.String({ pattern: 'A|B|C' }), Type.String())

Value.Check(T, 'A')                                  // false
Value.Check(T, 'B')                                  // false
Value.Check(T, 'C')                                  // false
Value.Check(T, 'D')                                  // true
```

#### Example 2

```typescript
const Even = Type.Number({ multipleOf: 2 })
const Odd  = Type.Not(Even, Type.Number())

Value.Check(Even, 0)                                  // true
Value.Check(Even, 1)                                  // false
Value.Check(Even, 2)                                  // true

Value.Check(Odd, 0)                                   // false
Value.Check(Odd, 1)                                   // true
Value.Check(Odd, 2)                                   // false
```

<a name="Extended-Type-Composite"></a>

## Standard Type (Composite)

Revision 0.26.0 includes a new `Composite` standard type. This type will combine an array of `TObject[]` into a `TObject` by taking a union of any overlapping properties.

```typescript
const A = Type.Object({ type: Type.Literal('A') })

const B = Type.Object({ type: Type.Literal('B') })

const C = Type.Object({ type: Type.Literal('C'), value: Type.Number() })

const T = Type.Composite([A, B, C])                  // type T = { 
                                                     //   type: 'A' | 'B' | 'C'
                                                     //   value: number
                                                     // }
```

<a name="Extended-Type-Symbol"></a>

## Extended Type (Symbol)

Revision 0.26.0 provides provisional support for `Symbol` type validation.

```typescript
const T = Type.Symbol()

Value.Check(A, Symbol('Foo'))                        // true
```

<a name="Extended-Type-BigInt"></a>

## Extended Type (BigInt)

Revision 0.26.0 provides provisional support for `BigInt` type validation.

```typescript
const T = Type.BigInt({ minimum: 10n })

Value.Check(B, 1_000_000n)                           // true
```

<a name="Breaking"></a>

## Breaking Changes

The following are breaking changed in Revision 0.26.0

<a name="Minimum-TypeScript-Version"></a>

## Minimum TypeScript Version

Revision 0.26.0 requires a minimum recommended TypeScript version of `4.2.3`. Version `4.1.5` is no longer supported.

<a name="Intersect-Schema-Representation"></a>

## Intersect Schema Representation

Revision 0.26.0 changes the schema representation for `Intersect`. Revision 0.25.0 would construct a composite `object` type, in 0.26.0, `Intersect` is expressed as `anyOf`. If upgrading, consider using `Type.Composite(...)` to return backwards compatible representations.

#### Intersect 0.25.0

```typescript
const T = Type.Intersect([                           // const U = {
  Type.Object({                                      //   type: 'object',
    x: Type.Number(),                                //   required: ['x', 'y'],  
  }),                                                //   properties: {  
  Type.Object({                                      //     x: {   
    y: Type.Number(),                                //       type: 'number'   
  })                                                 //     },   
])                                                   //     y: {     
                                                     //       type: 'number'   
                                                     //     }  
                                                     //   }  
                                                     // } 
```
#### Intersect 0.26.0

```typescript
const T = Type.Intersect([                          // const U = {
  Type.Object({                                     //  type: 'object', 
    x: Type.Number(),                               //  allOf: [{
  }),                                               //    type: 'object',
  Type.Object({                                     //    required: [ 'x' ],
    y: Type.Number(),                               //    properties: {
  })                                                //      x: { type: 'number' }
])                                                  //    }
                                                    //  }, {
                                                    //    type: 'object',
                                                    //    required: ['y'],
                                                    //    properties: {
                                                    //      y: { type: 'number' }
                                                    //    }
                                                    //  }]
                                                    // }
```

<a name="Never-Schema-Representation"></a>

## Never Schema Representation

Revision 0.26.0 simplifies the representation for `TNever`. Previous versions of TypeBox used an illogical intersection of Boolean constants via `allOf`. In 0.26.0, `never` is expressed as a `not` schema of type `any`.

#### Intersect 0.25.0

```typescript
const T = Type.Never()                               // const T = {
                                                     //   allOf: [
                                                     //     { type: 'boolean', const: true }
                                                     //     { type: 'boolean', const: false }
                                                     //   ]
                                                     // }
```
#### Intersect 0.26.0

```typescript
const T = Type.Never()                               // const T = { not: {} }
```

<a name="Value-Cast-and-Convert"></a>

## Value Cast and Convert

Revision 0.26.0 removes the `Cast` functions ability to coerce values. Use the new `Convert` function prior to `Cast`.

```typescript
const T = Type.Number()

const V = Value.Cast(T, '42')                        // const V = 42   - 0.25.0 coerces to 42

const V = Value.Cast(T, Value.Convert(T, '42'))      //  const V = 42   - 0.26.0 convert then cast
```

<a name="Movied TypeGuard Module"></a>

## Moved TypeGuard Module

The `TypeGuard` is now imported via the `@sinclair/typebox` module. This move is due to the TypeBox compositor internally using the guard when constructing types.

```typescript
import { TypeGuard } from '@sinclair/typebox/guard' // 0.25.0

import { TypeGuard } from '@sinclair/typebox'       // 0.26.0
```

<a name="Format-Renamed-to-FormatRegistry"></a>

## Format Renamed to FormatRegistry

The `Format` module has been renamed to `FormatRegistry` and moved to the `typebox.ts` module.

```typescript
import { Format } from '@sinclair/typebox/format'    // 0.25.0

import { FormatRegistry } from '@sinclair/typebox'   // 0.26.0
```

<a name="Custom-Renamed-to-TypeRegistry"></a>

## Custom Renamed to TypeRegistry

The `Format` module has been renamed to `FormatRegistry` and moved to the `typebox.ts` module.

```typescript
import { Custom } from '@sinclair/typebox/format' // 0.25.0

import { TypeRegistry } from '@sinclair/typebox'  // 0.26.0
```