deno.land / x / typebox@0.32.21 / changelog / 0.27.0.md
Revision 0.27.0 adds support for runtime Template Literal Types. 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.
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 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 defines Template Literals using back tick quoted strings which may include embedded union groups.
type T = `option${'A'|'B'}` // type T = 'optionA' | 'optionB'
type R = Record<T, string> // type R = {
// optionA: string
// optionB: string
// }
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.
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
// }
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.
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
// ]
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.
The following are breaking changes in Revision 0.27.0
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.
// 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.
Version Info