## [0.27.0](https://www.npmjs.com/package/@alkdev/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) ## Template Literal Types Revision 0.27.0 adds support for Template Literal types. These types operate as a form of computed `TUnion>`. 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 // 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`. 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 // type T = 'optionA' | 'optionB' type R = Static // 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 '@alkdev/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 // ] ``` ## 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) ## Breaking Changes The following are breaking changes in Revision 0.27.0 ## 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.