### 0.32.0

---

### Revision Updates

- [Revision 0.32.35](https://github.com/sinclairzx81/typebox/pull/914) Support Any for Record keys, Revert error message on required property, Fix order dependency for Union Convert.
- [Revision 0.32.34](https://github.com/sinclairzx81/typebox/pull/914) Fix template literal generation for template literals embedded within template literals.
- [Revision 0.32.33](https://github.com/sinclairzx81/typebox/pull/905) Pin ESM compiler target to ES2020. 
- [Revision 0.32.32](https://github.com/sinclairzx81/typebox/pull/898) Fix for Enum properties when used with Mapped types.
- [Revision 0.32.31](https://github.com/sinclairzx81/typebox/pull/881) Fix for Cast. Dereference Union variants before scoring.
- [Revision 0.32.30](https://github.com/sinclairzx81/typebox/pull/868) Support null object prototypes for Encode/Decode.
- [Revision 0.32.29](https://github.com/sinclairzx81/typebox/pull/862) Key derive optimization to improve Intersect Encode/Decode performance.
- [Revision 0.32.28](https://github.com/sinclairzx81/typebox/pull/861) Fix for TransformEncode introduced with 0.32.24, 0.32.25 optimizations.
- [Revision 0.32.27](https://github.com/sinclairzx81/typebox/pull/854) Support for esm.sh and general build tooling updates.
- [Revision 0.32.26](https://github.com/sinclairzx81/typebox/pull/851) Optimization for number checks, use Number.isFinite(x) over typeof `number`.
- [Revision 0.32.25](https://github.com/sinclairzx81/typebox/pull/849) Optimizations for type builder to improve schema creation performance for computed types.
- [Revision 0.32.24](https://github.com/sinclairzx81/typebox/pull/848) Optimizations for Convert to avoid unnecessary object initialization and cloning.
- [Revision 0.32.22](https://github.com/sinclairzx81/typebox/pull/840) Add Support for Optional and Readonly Function and Constructor Arguments.
- [Revision 0.32.21](https://github.com/sinclairzx81/typebox/pull/836) Refactor Array Conversion logic. Discard TNever on TComposite.
- [Revision 0.32.20](https://github.com/sinclairzx81/typebox/pull/810) Fix compiler regression (TS 5.3.3 -> 5.4.2) generating Diff declaration structures.
- [Revision 0.32.19](https://github.com/sinclairzx81/typebox/pull/805) Revert Union Convert logic added on 0.32.16.
- [Revision 0.32.18](https://github.com/sinclairzx81/typebox/pull/801) Add explicit return type on TypeSystem.Type.
- [Revision 0.32.17](https://github.com/sinclairzx81/typebox/pull/799) Detect ambiguous inference for StaticDecode when inferring as any.
- [Revision 0.32.16](https://github.com/sinclairzx81/typebox/pull/791) Enhance Composite, Mapped, Indexed and Transform types. Intersect and Union Convert updates, Include Path in Validation Error.
- [Revision 0.32.15](https://github.com/sinclairzx81/typebox/pull/774) Additional internal guards for Type Arrays, Map and Set structures.
- [Revision 0.32.14](https://github.com/sinclairzx81/typebox/pull/753) Use barrel exports for submodules.
- [Revision 0.32.13](https://github.com/sinclairzx81/typebox/pull/744) Add minLength and maxLength constraint for RegExp
- [Revision 0.32.12](https://github.com/sinclairzx81/typebox/pull/740) Fix option assignment on Record types.
- [Revision 0.32.11](https://github.com/sinclairzx81/typebox/pull/738) Optimize Extract, Exclude. Overloads for Template Literal
- [Revision 0.32.10](https://github.com/sinclairzx81/typebox/pull/734) Export additional type infrastructure for Partial and Required
- [Revision 0.32.9](https://github.com/sinclairzx81/typebox/pull/731) Generalize Composite to accept schematics of type TSchema[]
- [Revision 0.32.8](https://github.com/sinclairzx81/typebox/pull/728) Ensure schema `default` annotation is cloned on Create.
- [Revision 0.32.7](https://github.com/sinclairzx81/typebox/pull/727) Ensure schema `default` annotation is cloned on Default.
- [Revision 0.32.6](https://github.com/sinclairzx81/typebox/pull/724) Export additional type infrastructure for mapping types
- [Revision 0.32.5](https://github.com/sinclairzx81/typebox/pull/718) Update licence year span for 2024
- [Revision 0.32.4](https://github.com/sinclairzx81/typebox/pull/708) Ensure ErrorFunctionParameter type is exported
- [Revision 0.32.3](https://github.com/sinclairzx81/typebox/pull/703) Simplify Record Static Type
- [Revision 0.32.1](https://github.com/sinclairzx81/typebox/pull/701) Specify default exports for Web Pack


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

## Overview

Revision 0.32.0 adds support for ESM and carries out the work necessary to fully modularize the TypeBox type system to enable selective type imports. This revision also adds three new types (Mapped, Const, and Deref), along with two new Value functions (Clean and Default) as well as many enhancements to existing types (Index, KeyOf, RegExp, Optional and Readonly). This revision also carries out many internal optimizations to enhance type inference across all types.

This revision is a milestone revision for the TypeBox project. It has several breaking changes and requires a minor revision.

## Contents

- [Type Imports](#Type-Imports)
- [Value Function Import](#Value-Function-Imports)
- [CommonJS and ESM](#CommonJS-and-ESM)
- [Types](#Types)
  - [Mapped Type](#Types-Mapped-Type)
  - [Const Type](#Types-Const-Type)
  - [Deref Type](#Types-Deref-Type)
  - [RegExp Type](#Types-RegExp-Type)
  - [Subtract Modifiers](#Types-Subtract-Modifiers)
- [Values](#Values)
  - [Clean Function](#Values-Clean-Function)
  - [Default Function](#Values-Default-Function)
- [Errors](#Errors)
  - [Error Parameter](#Errors-Error-Parameter)
- [Optimizations](#Optimizations)
  - [Bundle Size](#Optimizations-Bundle-Size)
- [Breaking](#Breaking)
  - [Renamed Symbols](#Breaking-Renamed-Symbols)
  - [TypeGuard Interface Change](#Breaking-TypeGuard-Interface-Change)
  - [Value Submodule Imports](#Breaking-Value-Submodule-Imports)
  - [Error Function](#Breaking-Error-Function)
  - [RegEx](#Breaking-RegEx)

<a name="Type-Imports"></a>

### Type Imports

Revision 0.32.0 adds the ability to import types individually.

```typescript
import { Type, type Static } from '@sinclair/typebox'                   // classic   - 37.0 kb minified

import { Object, String, Number, type Static } from '@sinclair/typebox' // selective - 6.5 kb minified
```

<a name="Value-Function-Imports"></a>

### Value Function Imports

Revision 0.32.0 adds the ability to import value functions from the `/value` module path.

```typescript
import { Value } from '@sinclair/typebox/value'                         // classic   - 61.5 kb minified

import { Check } from '@sinclair/typebox/value'                         // selective - 18.2 kb minified
```

### CommonJS and ESM

<a name="CommonJS-and-ESM"></a>

Revision 0.32.0 now publishes both CommonJS and ESM builds of TypeBox. Existing CommonJS users should not be impacted by the addition of ESM. For ESM users however, particularily those using bundlers, it's now possible to benefit from deep tree shake optimizations provided by modern bundler tooling. 

<a name="Types"></a>

## Types

Revision 0.32.0 adds three new types to the type system and makes enhancements to Readonly and Optional modifiers.

<a name="Types-Mapped-Type"></a>

### Mapped Type

Revision 0.32.0 adds the Mapped type which replicates TS [Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) at runtime. The following shows the syntax comparison between TypeScript and TypeBox.

#### TypeScript

```typescript
type T = {
  x: number,
  y: number,
  z: number
}

type M = { [K in keyof T]: T[K] } // a mapped type
```
#### TypeBox
```typescript
const T = Type.Object({
  x: Type.Number(),
  y: Type.Number(),
  z: Type.Number()
})

const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) // a mapped type
```
Mapped types use a functional design to replicate the TypeScript feature. For users interested in this type, it may be helpful to use the [TypeBox Workbench](https://sinclairzx81.github.io/typebox-workbench/) which can generate runtime Mapped types from TypeScript syntax.

<a name="Types-Const-Type"></a>

### Const Type

Revision 0.32.0 adds a new Const type that creates `readonly` types from object, array and primitive literal values. This type analogs the TypeScript `as const` syntax. The following shows general usage.

```typescript
const A = Type.Const(1 as const)                               // const A: TLiteral<1>

const B = Type.Const([1, 2, 3] as const)                       // const B: TReadonly<TTuple<[
                                                               //   TLiteral<1>,
                                                               //   TLiteral<2>,
                                                               //   TLiteral<3>
                                                               // ]>>

const C = Type.Const({                                         // const C: TObject<{
  x: 1,                                                        //  x: TReadonly<TLiteral<1>>,
  y: 2,                                                        //  y: TReadonly<TLiteral<2>>,
  z: 3                                                         //  z: TReadonly<TLiteral<3>>,
} as const)                                                    // }>                                            
```
Revision 0.32.0 continues support for TypeScript 4.0, and because of this, the `as const` syntax must be appended to each literal value passed to the Const type. When TypeBox ends support for 4.0, updates will be made to this type to make use of [Const Type Parameters](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#const-type-parameters). This update will enable TypeBox to correctly infer the readonly literal type without the need for `as const`.


<a name="Types-Deref-Type"></a>

### Deref Type

Revision 0.32.0 adds a new Type.Deref type which can be used to dereference type schematics.

```typescript
const Vector = Type.Object({                                   // const Vector = {
  x: Type.Number(),                                            //   type: 'object',
  y: Type.Number(),                                            //   required: ['x', 'y', 'z'],
}, { $id: 'Vector' })                                          //   properties: {
                                                               //     x: { type: 'number' },
                                                               //     y: { type: 'number' }
                                                               //   },
                                                               //   $id: 'Vector'
                                                               // }

const VectorRef = Type.Ref(Vector)                             // const VectorRef = {
                                                               //   $ref: 'Vector'
                                                               // }
// ... Embedded Reference Type

const Vertex = Type.Object({                                   // const Vertex = {
  position: VectorRef,                                         //   type: 'object',
  texcoord: VectorRef,                                         //   required: ['position', 'texcoord'],
})                                                             //   properties: {
                                                               //     position: { $ref: 'Vector' },
                                                               //     texcoord: { $ref: 'Vector' }
                                                               //   }
                                                               // }

// ... Dereferenced Embedded Reference Type

const VertexDeref = Type.Deref(Vertex, [Vector])               // const VertexDeref = {
                                                               //   type: 'object',
                                                               //   required: ['position', 'texcoord'],
                                                               //   properties: {
                                                               //     position: {
                                                               //       type: 'object',
                                                               //       required: ['x', 'y', 'z'],
                                                               //       properties: {
                                                               //         x: { type: 'number' },
                                                               //         y: { type: 'number' }
                                                               //       }
                                                               //     },
                                                               //     texcoord: {
                                                               //       type: 'object',
                                                               //       required: ['x', 'y', 'z'],
                                                               //       properties: {
                                                               //         x: { type: 'number' },
                                                               //         y: { type: 'number' }
                                                               //       }
                                                               //     }
                                                               //   }
                                                               // }
```
The addition of Deref was prompted by issues composing reference types with mapping types (such as Partial, Required, Pick and Omit) which is generally not supported. Prior to Revision 0.32.0, there was some expectation for users to maintain and dereference types manually. In 0.32.0, users will still need to maintain references, but Deref will offer a more convenient mechanism to normalize reference types prior to composition.


<a name="Types-RegExp-Type"></a>

### RegExp Type

Revision 0.32.0 updates RegExp to support the full ECMA 262 regular expression syntax. In previous revisions, this type had been expressed as an alias for `TString` with a `pattern` to try ensure compliance with the [regular expression](https://json-schema.org/understanding-json-schema/reference/regular_expressions) subset supported by Json Schema. In Revision 0.32.0, RegExp is given a new type representation unto itself (named `TRegExp`) which houses both `source` and `flags` properties used to reconstruct a JavaScript regular expression object, making it properly distinct from `TString` and fully supportive of UTF-16.

```typescript
// Case Insensitive

const T = Type.RegExp(/abc/i)                                  // const T = {
                                                               //   type: 'RegExp',
                                                               //   source: 'abc',
                                                               //   flags: 'i'
                                                               // }

type T = Static<typeof T>                                      // type T = string

Value.Check(T, 'abc')                                          // ok
Value.Check(T, 'ABC')                                          // ok

// Extended Syntax

const E = Type.RegExp(/<a?:.+?:\d{18}>|\p{Extended_Pictographic}/gu)

Value.Check(E, '♥️♦️♠️♣️')                                         // ok - emoji supported
```

The RegExp type can be thought of as a more capable TemplateLiteral that can only reasonably infer as `string`. Additionally, the RegExp inference type of `string` is unique to the other `[JavaScript]` types in that it does not infer as it's named type. The updates to RegExp were prompted by the limitations with Json Schema expressions, and to provide better options for users requiring general Unicode validation support. For Json Schema compliance, the recommendation moving forward will be to use either String with pattern or TemplateLiteral.

```typescript
const T = Type.String({ pattern: '^(a|b|c)$' })                // Json Schema compliant

const T = Type.TemplateLiteral('${a|b|c}')                     // Json Schema compliant

const T = Type.RegExp(/$(a|b|c)$/)                             // Non Json Schema compliant
```

<a name="Types-Subtractive-Modifiers"></a>

### Subtract Modifier

Revision 0.32.0 adds new overloads for Readonly and Optional modifiers that enable them to subtract (or remove) that modifier from a type. Both Readonly and Optional now accept an optional secondary boolean argument that if `false`, will remove the modifier.

#### TypeScript
```typescript
type T = {
  x?: number,
  y?: number
}
type M = { [K in keyof T]-?: T[K] } // -? - subtract optional modifier
```
#### TypeBox
```typescript
const T = Type.Object({
  x: Type.Optional(Type.Number()),
  y: Type.Optional(Type.Number())
})
const M = Type.Mapped(Type.KeyOf(T), K => {
  return Type.Optional(Type.Index(T, K), false) // false - subtract optional modifier
})
```
Subtractive modifiers are provided in support of the new Mapped type feature.

<a name="Values"></a>

## Values

Revision 0.32.0 adds two new functions to the Value module.

<a name="Values-Clean-Function"></a>

### Clean Function

Revision 0.32.0 adds a new Clean function that can be used to omit any values unknown to the type. This function will work irrespective of if `additionalProperties` is specified on the type. The Clean function is intended to replicate the functionality of Ajv's `removeAdditional` configuration.

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

const X = Value.Clean(T, null)                                  // const 'X = null

const Y = Value.Clean(T, { x: 1 })                              // const 'Y = { x: 1 }

const Z = Value.Clean(T, { x: 1, y: 2, z: 3 })                  // const 'Z = { x: 1, y: 2 }
```

Note: the Clean function does not check the validity of the value being cleaned, and does not provide assurances that the result will be valid. Its return value is `unknown` and should be checked before use.

<a name="Values-Default-Function"></a>

### Default Function

Revision 0.32.0 adds a new Default function that can be used to add missing values if the type specifies a `default` annotation. This function is intended to replicate Ajv's `useDefaults` functionality.

```typescript
const T = Type.Object({ 
  x: Type.Number({ default: 0 }), 
  y: Type.Number({ default: 0 })
})

const X = Value.Default(T, null)                               // const 'X = null - non-enumerable

const Y = Value.Default(T, { })                                // const 'Y = { x: 0, y: 0 }

const Z = Value.Default(T, { x: 1 })                           // const 'Z = { x: 1, y: 0 }
```

The Default function does not check the validity of the value being defaulted, and does not provide assurances that the result will be valid. Its return value is `unknown` and should be checked before use.

<a name="Optimizations"></a>

## Optimizations

Following the work to modularize TypeBox's type system, additional optimizations were carried out across each submodule to only import dependent type infrastructure. This has led to some fairly significant reductions in output sizes across each submodule. The main TypeBox import has increased in size due in part to the new Mapped types feature and other associative types, however selective imports supported on this revision should offer options for users concerned about output bundle size. There will be contined work to optimize the new type system throughout 0.32.0 and subsequent revisions.

The following shows the comparisons between 0.31.0 and 0.32.0.

<a name="Optimizations-Bundle-Size"></a>

```typescript
// Revision 0.31.0

┌──────────────────────┬────────────┬────────────┬─────────────┐
│       (index)        │  Compiled  │  Minified  │ Compression │
├──────────────────────┼────────────┼────────────┼─────────────┤
│ typebox/compiler     │ '163.6 kb' │ ' 71.6 kb' │  '2.28 x'   │
│ typebox/errors       │ '113.3 kb' │ ' 50.1 kb' │  '2.26 x'   │
│ typebox/system       │ ' 83.9 kb' │ ' 37.5 kb' │  '2.24 x'   │
│ typebox/value        │ '191.1 kb' │ ' 82.3 kb' │  '2.32 x'   │
│ typebox              │ ' 73.8 kb' │ ' 32.3 kb' │  '2.29 x'   │
└──────────────────────┴────────────┴────────────┴─────────────┘

//  Revision 0.32.0

┌──────────────────────┬────────────┬────────────┬─────────────┐
│       (index)        │  Compiled  │  Minified  │ Compression │
├──────────────────────┼────────────┼────────────┼─────────────┤
│ typebox/compiler     │ '120.6 kb' │ ' 52.9 kb' │  '2.28 x'   │
│ typebox/errors       │ ' 55.7 kb' │ ' 25.5 kb' │  '2.19 x'   │
│ typebox/system       │ '  4.7 kb' │ '  2.0 kb' │  '2.33 x'   │
│ typebox/value        │ '146.2 kb' │ ' 62.0 kb' │  '2.36 x'   │
│ typebox              │ ' 91.4 kb' │ ' 37.8 kb' │  '2.42 x'   │
└──────────────────────┴────────────┴────────────┴─────────────┘
```
<a name="Errors"></a>

## Errors

Revision 0.32.0 makes some enhancements to errors.

<a name="Errors-Error-Parameter"></a>

### Error Parameter

Revision 0.32.0 updates TypeBox's ErrorFunction to accept an ErrorParameter that contains additional information regarding the cause of a validation error. In Revision 0.31.0, only `errorType` and `schema` were passed through to this function. In 0.32.0 the additional properties `value` and `path` are also passed through. This update was prompted by some users needing to be able to generate specific error messages derived from specific values or other associated information.

The following shows the changes from 0.31.0 to 0.32.0.

```typescript
// Revision 0.31.0

import { TypeSystemErrorFunction } from '@sinclair/typebox/system'

TypeSystemErrorFunction.Set((schema, errorType) => {

   return 'oh no, an error!'
})

// Revision 0.32.0

import { SetErrorFunction } from '@sinclair/typebox/errors'

SetErrorFunction(({ schema, errorType, path, value }) => { // as destructured object

  return 'oh no, an error!'
})
```
Note that Revision 0.32.0 does make a breaking interface change by moving the ErrorFunction from `/system` to `/errors`. See breaking changes for more information.

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

## Breaking

The following list the breaking changes in Revision 0.32.0.


<a name="Breaking-Renamed-Symbols"></a>

### Renamed Symbols

Revision 0.32.0 renames the `Optional`, `Required` and `Transform` symbols to `OptionalKind`, `RequiredKind` and `TransformKind`. This change was necessary to avoid conflicts with exported type functions.

```typescript
// Revision 0.31.0
import { Kind, Hint, Optional, Required, Transform } from '@sinclair/typebox' // these are symbols

// Revision 0.32.0
import { 
  Kind, Hint, OptionalKind, RequiredKind, TransformKind,                      // these are symbols
  Optional, Required, Transform                                               // these are type imports
} from '@sinclair/typebox' 
```

<a name="Breaking-TypeGuard-Interface-Change"></a>

### TypeGuard Interface Change

Revision 0.32.0 has a breaking interface change on the TypeGuard utility where the `T` prefixed guard functions have been updated to use the `Is` prefix. This naming change is perhaps somewhat more sensible than the previous naming, however the update was largely prompted by TypeScript compiler issues where interface types (i.e. `TString`) where conflicting with the `TString` functions leading to breakage in CommonJS.

```typescript
// Revision 0.31.0

import { TypeGuard, Kind } from '@sinclair/typebox'

const R = TypeGuard.TString({ ... })

// Revision 0.32.0

import { TypeGuard } from '@sinclair/typebox'

const R = TypeGuard.IsString({ ... })
```

<a name="Breaking-Value-Submodule-Imports"></a>

### Value Submodule Imports

The value submodule function import paths are unfortunately no longer supported. Instead, these can be imported directly on the `/value` path. The need to break the submodule paths was mostly due to complexities configuring dual ESM and CommonJS publishing for the package, as well as retaining support for pre and post node16 module resolution (of which many complexities reside, both for Node as well as for TypeScript type module resolution)

```typescript
// Revision 0.31.0

import { Check } from '@sinclair/typebox/value/check'

// Revision 0.32.0

import { Check } from '@sinclair/typebox/value'
```

<a name="Breaking-Error-Function"></a>

### Error Function

The TypeSystemErrorFunction has been replaced with SetErrorFunction which can be imported on the `/errors` submodule. This change is generally a tidy up, and to reserve the `/system` submodule for type system policy configuration, as well as future Json Schema generation options (draft 2020-12)

```typescript
// Revision 0.31.0

import { TypeSystemErrorFunction, ValueErrorType, DefaultErrorFunction } from '@sinclair/typebox/system'

TypeSystemErrorFunction.Set((schema, errorType) => { // i18n override
  switch(errorType) {
    /* en-US */ case ValueErrorType.String: return 'Expected string'
    /* fr-FR */ case ValueErrorType.Number: return 'Nombre attendu'  
    /* ko-KR */ case ValueErrorType.Boolean: return '예상 부울'      
    /* en-US */ default: return DefaultErrorFunction(schema, errorType)          
  }
})

// Revision 0.32.0

import { SetErrorFunction, ValueErrorType, DefaultErrorFunction } from '@sinclair/typebox/errors'

SetErrorFunction((error) => { // i18n override
  switch(error.errorType) {
    /* en-US */ case ValueErrorType.String: return 'Expected string'
    /* fr-FR */ case ValueErrorType.Number: return 'Nombre attendu'  
    /* ko-KR */ case ValueErrorType.Boolean: return '예상 부울'      
    /* en-US */ default: return DefaultErrorFunction(error)          
  }
})
```

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

### RegEx

This RegEx function was flagged for deprecation on 0.30.0. It has been removed on Revision 0.32.0. Use the Type.RegExp type, or Type.String with a pattern to remain compatible with the Json Schema specification.

```typescript
// Revision 0.31.0

const T = Type.RegEx(/abc/)                                    // deprecation warning

// Revision 0.32.0

const A = Type.RegExp(/abc/)                                   // JavaScript Type

const B = Type.String({ pattern: /abc/.source })               // Json Type
```