Publish
This commit is contained in:
152
changelog/0.27.0.md
Normal file
152
changelog/0.27.0.md
Normal file
@@ -0,0 +1,152 @@
|
||||
## [0.27.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.27.0)
|
||||
|
||||
## Overview
|
||||
|
||||
Revision 0.27.0 adds support for runtime [Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html). This revision does not include any functional breaking changes but does rename some public type aliases. As such this revision requires a minor semver increment.
|
||||
|
||||
## Contents
|
||||
|
||||
- Enhancements
|
||||
- [Template Literal Types](#Template-Literal-Types)
|
||||
- [TemplateLiteralParser](#TemplateLiteralParser)
|
||||
- [WorkBench](#WorkBench)
|
||||
- Breaking Changes
|
||||
- [TSelf renamed to TThis](#TSelf-renamed-to-TThis)
|
||||
|
||||
|
||||
<a href="Template-Literal-Types"></a>
|
||||
|
||||
## Template Literal Types
|
||||
|
||||
Revision 0.27.0 adds support for Template Literal types. These types operate as a form of computed `TUnion<TLiteral<string>>`. TypeBox encodes template literals using a subset of [ECMA 262](https://json-schema.org/understanding-json-schema/reference/regular_expressions.html) regular erxpressions which are applied to `pattern` properties of type `string`. This encoding enables JSON Schema validators to assert using existing regular expression checks.
|
||||
|
||||
### TypeScript
|
||||
|
||||
TypeScript defines Template Literals using back tick quoted strings which may include embedded union groups.
|
||||
|
||||
```typescript
|
||||
type T = `option${'A'|'B'}` // type T = 'optionA' | 'optionB'
|
||||
|
||||
type R = Record<T, string> // type R = {
|
||||
// optionA: string
|
||||
// optionB: string
|
||||
// }
|
||||
```
|
||||
|
||||
### TypeBox
|
||||
|
||||
TypeBox defines Template Literals using the `TemplateLiteral` function. This function accepts a sequence of TLiteral, TString, TNumber, TInteger and TBigInt which describe a sequence concatenations. The embedded TUnion type defines an option group which can later be expanded into a set of `TLiteral<string>`. This expansion enables Template Literal types to also be used as Record keys.
|
||||
|
||||
```typescript
|
||||
const T = Type.TemplateLiteral([ // const T = {
|
||||
Type.Literal('option'), // pattern: '^option(A|B)$',
|
||||
Type.Union([ // type: 'string'
|
||||
Type.Literal('A'), // }
|
||||
Type.Literal('B')
|
||||
])
|
||||
])
|
||||
|
||||
const R = Type.Record(T, Type.String()) // const R = {
|
||||
// type: 'object',
|
||||
// required: ['optionA', 'optionB'],
|
||||
// properties: {
|
||||
// optionA: {
|
||||
// type: 'string'
|
||||
// },
|
||||
// optionB: {
|
||||
// type: 'string'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
type T = Static<typeof T> // type T = 'optionA' | 'optionB'
|
||||
|
||||
type R = Static<typeof R> // type R = {
|
||||
// optionA: string
|
||||
// optionB: string
|
||||
// }
|
||||
```
|
||||
|
||||
## TemplateLiteralParser
|
||||
|
||||
Template Literal types are encoded as `string` patterns. Because these types also need to act as composable union types, Revision 0.27.0 includes an expression parser / generator system specifically for regular expressions. This system is used during composition to allow templates to compose with other types, but can also be used in isolation to generate string sequences for the supported expression grammar. This functionality may be provided as standard on the `Value.*` sub module in subsequent revisions.
|
||||
|
||||
The following generates a 8-bit binary sequence for the given expression.
|
||||
|
||||
```typescript
|
||||
|
||||
import { TemplateLiteralParser, TemplateLiteralGenerator, TemplateLiteralFinite } from '@sinclair/typebox'
|
||||
|
||||
const Bit = `(0|1)` // bit union
|
||||
const Byte = `${Bit}${Bit}${Bit}${Bit}${Bit}${Bit}${Bit}${Bit}` // byte sequence
|
||||
|
||||
const E = TemplateLiteralParser.Parse(Byte) // parsed expression tree
|
||||
const F = TemplateLiteralFinite.Check(E) // is the expression finite?
|
||||
const S = [...TemplateLiteralGenerator.Generate(E)] // generate sequence
|
||||
|
||||
// const S = [ // computed sequence
|
||||
// '00000000', '00000001', '00000010', '00000011', '00000100',
|
||||
// '00000101', '00000110', '00000111', '00001000', '00001001',
|
||||
// '00001010', '00001011', '00001100', '00001101', '00001110',
|
||||
// '00001111', '00010000', '00010001', '00010010', '00010011',
|
||||
// '00010100', '00010101', '00010110', '00010111', '00011000',
|
||||
// '00011001', '00011010', '00011011', '00011100', '00011101',
|
||||
// '00011110', '00011111', '00100000', '00100001', '00100010',
|
||||
// '00100011', '00100100', '00100101', '00100110', '00100111',
|
||||
// '00101000', '00101001', '00101010', '00101011', '00101100',
|
||||
// '00101101', '00101110', '00101111', '00110000', '00110001',
|
||||
// '00110010', '00110011', '00110100', '00110101', '00110110',
|
||||
// '00110111', '00111000', '00111001', '00111010', '00111011',
|
||||
// '00111100', '00111101', '00111110', '00111111', '01000000',
|
||||
// '01000001', '01000010', '01000011', '01000100', '01000101',
|
||||
// '01000110', '01000111', '01001000', '01001001', '01001010',
|
||||
// '01001011', '01001100', '01001101', '01001110', '01001111',
|
||||
// '01010000', '01010001', '01010010', '01010011', '01010100',
|
||||
// '01010101', '01010110', '01010111', '01011000', '01011001',
|
||||
// '01011010', '01011011', '01011100', '01011101', '01011110',
|
||||
// '01011111', '01100000', '01100001', '01100010', '01100011',
|
||||
// ... 156 more items
|
||||
// ]
|
||||
```
|
||||
|
||||
<a href="Workbench"></a>
|
||||
|
||||
## Workbench
|
||||
|
||||
To assist with TypeScript alignment and to prototype new features. A new web based compiler tool has been written that allows interactive cross compiling between TypeScript and TypeBox. This tool will be enhanced seperately from the TypeBox project, but can be used to quickly generate TypeBox type definitions from existing TypeScript types.
|
||||
|
||||
[TypeBox Workbench Application](https://sinclairzx81.github.io/typebox-workbench)
|
||||
|
||||
[TypeBox Workbench Project](https://github.com/sinclairzx81/typebox-workbench)
|
||||
|
||||
<a href="https://sinclairzx81.github.io/typebox-workbench/"><img src="https://github.com/sinclairzx81/typebox-workbench/raw/main/typebox.png" /></a>
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
The following are breaking changes in Revision 0.27.0
|
||||
|
||||
<a href="TSelf-renamed-to-TThis"></a>
|
||||
|
||||
## TSelf renamed to TThis
|
||||
|
||||
This rename is to align with TypeScript interfaces. Unlike `type` aliases, TypeScript `interface` types include a implicit `this` type. This change relates specifically to TypeBox's current Recursive type which passes the `TThis` parameter via callback. The `TThis` parameter can be seen as analogous to the implicit TypeScript interface `this`.
|
||||
|
||||
Consider the following.
|
||||
|
||||
```typescript
|
||||
// type T = { id: string, nodes: this[] } // error: no implicit this
|
||||
|
||||
interface Node { // ok: this is implicit for interfaces
|
||||
id: string,
|
||||
nodes: this[]
|
||||
}
|
||||
|
||||
const T = Type.Recursive(This => // `This` === implicit 'this' for interface
|
||||
Type.Object({ //
|
||||
id: Type.String(), // Should `Recursive` be renamed to `Interface`?
|
||||
nodes: Type.Array(This)
|
||||
})
|
||||
)
|
||||
```
|
||||
Future revisions may rename `Recurisve` to `Interface`, but for now, just the `TSelf` has been renamed.
|
||||
Reference in New Issue
Block a user