## [0.26.0](https://www.npmjs.com/package/@alkdev/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)
## 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 '@alkdev/typebox'
const T = Type.Date() // error: no such function
```
## 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
```
## 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;
// }
```
## 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
// ^ number
type T2 = Exclude
// ^ string
```
#### TypeBox
```typescript
const T0 = Type.Extends(Type.String(), Type.Number(), Type.Literal(true), Type.Literal(false))
// ^ TLiteral
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
```
## 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
```
## 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', ... }]
```
## 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 '@alkdev/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)
// )
// }
```
## 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
```
## 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
// }
```
## 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
```
## 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
```
## Breaking Changes
The following are breaking changed in Revision 0.26.0
## 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.
## 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' }
// }
// }]
// }
```
## 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: {} }
```
## 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
```
## Moved TypeGuard Module
The `TypeGuard` is now imported via the `@alkdev/typebox` module. This move is due to the TypeBox compositor internally using the guard when constructing types.
```typescript
import { TypeGuard } from '@alkdev/typebox/guard' // 0.25.0
import { TypeGuard } from '@alkdev/typebox' // 0.26.0
```
## Format Renamed to FormatRegistry
The `Format` module has been renamed to `FormatRegistry` and moved to the `typebox.ts` module.
```typescript
import { Format } from '@alkdev/typebox/format' // 0.25.0
import { FormatRegistry } from '@alkdev/typebox' // 0.26.0
```
## Custom Renamed to TypeRegistry
The `Format` module has been renamed to `FormatRegistry` and moved to the `typebox.ts` module.
```typescript
import { Custom } from '@alkdev/typebox/format' // 0.25.0
import { TypeRegistry } from '@alkdev/typebox' // 0.26.0
```