@sinclair/typebox 0.26.8 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/typebox.js CHANGED
@@ -27,13 +27,22 @@ THE SOFTWARE.
27
27
 
28
28
  ---------------------------------------------------------------------------*/
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.Type = exports.StandardType = exports.ExtendedTypeBuilder = exports.StandardTypeBuilder = exports.TypeBuilder = exports.KeyResolver = exports.ObjectMap = exports.TypeClone = exports.TypeExtends = exports.TypeExtendsResult = exports.ExtendsUndefined = exports.TypeGuard = exports.TypeGuardUnknownTypeError = exports.FormatRegistry = exports.TypeRegistry = exports.Kind = exports.Hint = exports.Modifier = void 0;
30
+ exports.Type = exports.StandardType = exports.ExtendedTypeBuilder = exports.StandardTypeBuilder = exports.TypeBuilder = exports.TemplateLiteralGenerator = exports.TemplateLiteralFinite = exports.TemplateLiteralParser = exports.TemplateLiteralParserError = exports.TemplateLiteralResolver = exports.TemplateLiteralPattern = exports.KeyResolver = exports.ObjectMap = exports.TypeClone = exports.TypeExtends = exports.TypeExtendsResult = exports.ExtendsUndefined = exports.TypeGuard = exports.TypeGuardUnknownTypeError = exports.FormatRegistry = exports.TypeRegistry = exports.PatternStringExact = exports.PatternNumberExact = exports.PatternBooleanExact = exports.PatternString = exports.PatternNumber = exports.PatternBoolean = exports.Kind = exports.Hint = exports.Modifier = void 0;
31
31
  // --------------------------------------------------------------------------
32
- // Compositing Symbols
32
+ // Symbols
33
33
  // --------------------------------------------------------------------------
34
34
  exports.Modifier = Symbol.for('TypeBox.Modifier');
35
35
  exports.Hint = Symbol.for('TypeBox.Hint');
36
36
  exports.Kind = Symbol.for('TypeBox.Kind');
37
+ // --------------------------------------------------------------------------
38
+ // Patterns
39
+ // --------------------------------------------------------------------------
40
+ exports.PatternBoolean = '(true|false)';
41
+ exports.PatternNumber = '(0|[1-9][0-9]*)';
42
+ exports.PatternString = '.*';
43
+ exports.PatternBooleanExact = `^${exports.PatternBoolean}$`;
44
+ exports.PatternNumberExact = `^${exports.PatternNumber}$`;
45
+ exports.PatternStringExact = `^${exports.PatternString}$`;
37
46
  /** A registry for user defined types */
38
47
  var TypeRegistry;
39
48
  (function (TypeRegistry) {
@@ -183,7 +192,7 @@ var TypeGuard;
183
192
  IsOptionalBoolean(schema.uniqueItems));
184
193
  }
185
194
  TypeGuard.TArray = TArray;
186
- /** Returns true if the given schema is TSymbol */
195
+ /** Returns true if the given schema is TBigInt */
187
196
  function TBigInt(schema) {
188
197
  // prettier-ignore
189
198
  return (TKind(schema) &&
@@ -404,15 +413,6 @@ var TypeGuard;
404
413
  return true;
405
414
  }
406
415
  TypeGuard.TRecord = TRecord;
407
- /** Returns true if the given schema is TSelf */
408
- function TSelf(schema) {
409
- // prettier-ignore
410
- return (TKind(schema) &&
411
- schema[exports.Kind] === 'Self' &&
412
- IsOptionalString(schema.$id) &&
413
- IsString(schema.$ref));
414
- }
415
- TypeGuard.TSelf = TSelf;
416
416
  /** Returns true if the given schema is TRef */
417
417
  function TRef(schema) {
418
418
  // prettier-ignore
@@ -444,6 +444,26 @@ var TypeGuard;
444
444
  IsOptionalString(schema.$id));
445
445
  }
446
446
  TypeGuard.TSymbol = TSymbol;
447
+ /** Returns true if the given schema is TTemplateLiteral */
448
+ function TTemplateLiteral(schema) {
449
+ // prettier-ignore
450
+ return (TKind(schema) &&
451
+ schema[exports.Kind] === 'TemplateLiteral' &&
452
+ schema.type === 'string' &&
453
+ IsString(schema.pattern) &&
454
+ schema.pattern[0] === '^' &&
455
+ schema.pattern[schema.pattern.length - 1] === '$');
456
+ }
457
+ TypeGuard.TTemplateLiteral = TTemplateLiteral;
458
+ /** Returns true if the given schema is TThis */
459
+ function TThis(schema) {
460
+ // prettier-ignore
461
+ return (TKind(schema) &&
462
+ schema[exports.Kind] === 'This' &&
463
+ IsOptionalString(schema.$id) &&
464
+ IsString(schema.$ref));
465
+ }
466
+ TypeGuard.TThis = TThis;
447
467
  /** Returns true if the given schema is TTuple */
448
468
  function TTuple(schema) {
449
469
  // prettier-ignore
@@ -565,10 +585,11 @@ var TypeGuard;
565
585
  TObject(schema) ||
566
586
  TPromise(schema) ||
567
587
  TRecord(schema) ||
568
- TSelf(schema) ||
569
588
  TRef(schema) ||
570
589
  TString(schema) ||
571
590
  TSymbol(schema) ||
591
+ TTemplateLiteral(schema) ||
592
+ TThis(schema) ||
572
593
  TTuple(schema) ||
573
594
  TUndefined(schema) ||
574
595
  TUnion(schema) ||
@@ -1038,17 +1059,17 @@ var TypeExtends;
1038
1059
  // Record
1039
1060
  // --------------------------------------------------------------------------
1040
1061
  function RecordKey(schema) {
1041
- if ('^(0|[1-9][0-9]*)$' in schema.patternProperties)
1062
+ if (exports.PatternNumberExact in schema.patternProperties)
1042
1063
  return exports.Type.Number();
1043
- if ('^.*$' in schema.patternProperties)
1064
+ if (exports.PatternStringExact in schema.patternProperties)
1044
1065
  return exports.Type.String();
1045
1066
  throw Error('TypeExtends: Cannot get record key');
1046
1067
  }
1047
1068
  function RecordValue(schema) {
1048
- if ('^(0|[1-9][0-9]*)$' in schema.patternProperties)
1049
- return schema.patternProperties['^(0|[1-9][0-9]*)$'];
1050
- if ('^.*$' in schema.patternProperties)
1051
- return schema.patternProperties['^.*$'];
1069
+ if (exports.PatternNumberExact in schema.patternProperties)
1070
+ return schema.patternProperties[exports.PatternNumberExact];
1071
+ if (exports.PatternStringExact in schema.patternProperties)
1072
+ return schema.patternProperties[exports.PatternStringExact];
1052
1073
  throw Error('TypeExtends: Cannot get record value');
1053
1074
  }
1054
1075
  function RecordRight(left, right) {
@@ -1269,6 +1290,12 @@ var TypeExtends;
1269
1290
  return TypeGuard.TVoid(right) ? TypeExtendsResult.True : TypeExtendsResult.False;
1270
1291
  }
1271
1292
  function Visit(left, right) {
1293
+ // template union remap
1294
+ if (TypeGuard.TTemplateLiteral(left))
1295
+ return Visit(TemplateLiteralResolver.Resolve(left), right);
1296
+ if (TypeGuard.TTemplateLiteral(right))
1297
+ return Visit(left, TemplateLiteralResolver.Resolve(right));
1298
+ // standard extends
1272
1299
  if (TypeGuard.TAny(left))
1273
1300
  return Any(left, right);
1274
1301
  if (TypeGuard.TArray(left))
@@ -1295,14 +1322,14 @@ var TypeExtends;
1295
1322
  return Null(left, right);
1296
1323
  if (TypeGuard.TNumber(left))
1297
1324
  return Number(left, right);
1325
+ if (TypeGuard.TObject(left))
1326
+ return Object(left, right);
1298
1327
  if (TypeGuard.TRecord(left))
1299
1328
  return Record(left, right);
1300
1329
  if (TypeGuard.TString(left))
1301
1330
  return String(left, right);
1302
1331
  if (TypeGuard.TSymbol(left))
1303
1332
  return Symbol(left, right);
1304
- if (TypeGuard.TObject(left))
1305
- return Object(left, right);
1306
1333
  if (TypeGuard.TTuple(left))
1307
1334
  return Tuple(left, right);
1308
1335
  if (TypeGuard.TPromise(left))
@@ -1422,6 +1449,278 @@ var KeyResolver;
1422
1449
  KeyResolver.Resolve = Resolve;
1423
1450
  })(KeyResolver = exports.KeyResolver || (exports.KeyResolver = {}));
1424
1451
  // --------------------------------------------------------------------------
1452
+ // TemplateLiteralPattern
1453
+ // --------------------------------------------------------------------------
1454
+ var TemplateLiteralPattern;
1455
+ (function (TemplateLiteralPattern) {
1456
+ function Escape(value) {
1457
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1458
+ }
1459
+ function Visit(schema, acc) {
1460
+ if (TypeGuard.TTemplateLiteral(schema)) {
1461
+ const pattern = schema.pattern.slice(1, schema.pattern.length - 1);
1462
+ return pattern;
1463
+ }
1464
+ else if (TypeGuard.TUnion(schema)) {
1465
+ const tokens = schema.anyOf.map((schema) => Visit(schema, acc)).join('|');
1466
+ return `(${tokens})`;
1467
+ }
1468
+ else if (TypeGuard.TNumber(schema)) {
1469
+ return `${acc}${exports.PatternNumber}`;
1470
+ }
1471
+ else if (TypeGuard.TInteger(schema)) {
1472
+ return `${acc}${exports.PatternNumber}`;
1473
+ }
1474
+ else if (TypeGuard.TBigInt(schema)) {
1475
+ return `${acc}${exports.PatternNumber}`;
1476
+ }
1477
+ else if (TypeGuard.TString(schema)) {
1478
+ return `${acc}${exports.PatternString}`;
1479
+ }
1480
+ else if (TypeGuard.TLiteral(schema)) {
1481
+ return `${acc}${Escape(schema.const.toString())}`;
1482
+ }
1483
+ else if (TypeGuard.TBoolean(schema)) {
1484
+ return `${acc}${exports.PatternBoolean}`;
1485
+ }
1486
+ else if (TypeGuard.TNever(schema)) {
1487
+ throw Error('TemplateLiteralPattern: TemplateLiteral cannot operate on types of TNever');
1488
+ }
1489
+ else {
1490
+ throw Error(`TemplateLiteralPattern: Unexpected Kind '${schema[exports.Kind]}'`);
1491
+ }
1492
+ }
1493
+ function Create(kinds) {
1494
+ return `^${kinds.map((schema) => Visit(schema, '')).join('')}\$`;
1495
+ }
1496
+ TemplateLiteralPattern.Create = Create;
1497
+ })(TemplateLiteralPattern = exports.TemplateLiteralPattern || (exports.TemplateLiteralPattern = {}));
1498
+ // --------------------------------------------------------------------------------------
1499
+ // TemplateLiteralResolver
1500
+ // --------------------------------------------------------------------------------------
1501
+ var TemplateLiteralResolver;
1502
+ (function (TemplateLiteralResolver) {
1503
+ function Resolve(template) {
1504
+ const expression = TemplateLiteralParser.ParseExact(template.pattern);
1505
+ if (!TemplateLiteralFinite.Check(expression))
1506
+ return exports.Type.String();
1507
+ const literals = [...TemplateLiteralGenerator.Generate(expression)].map((value) => exports.Type.Literal(value));
1508
+ return exports.Type.Union(literals);
1509
+ }
1510
+ TemplateLiteralResolver.Resolve = Resolve;
1511
+ })(TemplateLiteralResolver = exports.TemplateLiteralResolver || (exports.TemplateLiteralResolver = {}));
1512
+ // --------------------------------------------------------------------------------------
1513
+ // TemplateLiteralParser
1514
+ // --------------------------------------------------------------------------------------
1515
+ class TemplateLiteralParserError extends Error {
1516
+ constructor(message) {
1517
+ super(message);
1518
+ }
1519
+ }
1520
+ exports.TemplateLiteralParserError = TemplateLiteralParserError;
1521
+ var TemplateLiteralParser;
1522
+ (function (TemplateLiteralParser) {
1523
+ function Unescape(value) {
1524
+ return value.replace(/\\/g, '');
1525
+ }
1526
+ function IsNonEscaped(pattern, index, char) {
1527
+ return pattern[index] === char && pattern.charCodeAt(index - 1) !== 92;
1528
+ }
1529
+ function IsOpenParen(pattern, index) {
1530
+ return IsNonEscaped(pattern, index, '(');
1531
+ }
1532
+ function IsCloseParen(pattern, index) {
1533
+ return IsNonEscaped(pattern, index, ')');
1534
+ }
1535
+ function IsSeparator(pattern, index) {
1536
+ return IsNonEscaped(pattern, index, '|');
1537
+ }
1538
+ function IsGroup(pattern) {
1539
+ if (!(IsOpenParen(pattern, 0) && IsCloseParen(pattern, pattern.length - 1)))
1540
+ return false;
1541
+ let count = 0;
1542
+ for (let index = 0; index < pattern.length; index++) {
1543
+ if (IsOpenParen(pattern, index))
1544
+ count += 1;
1545
+ if (IsCloseParen(pattern, index))
1546
+ count -= 1;
1547
+ if (count === 0 && index !== pattern.length - 1)
1548
+ return false;
1549
+ }
1550
+ return true;
1551
+ }
1552
+ function InGroup(pattern) {
1553
+ return pattern.slice(1, pattern.length - 1);
1554
+ }
1555
+ function IsPrecedenceOr(pattern) {
1556
+ let count = 0;
1557
+ for (let index = 0; index < pattern.length; index++) {
1558
+ if (IsOpenParen(pattern, index))
1559
+ count += 1;
1560
+ if (IsCloseParen(pattern, index))
1561
+ count -= 1;
1562
+ if (IsSeparator(pattern, index) && count === 0)
1563
+ return true;
1564
+ }
1565
+ return false;
1566
+ }
1567
+ function IsPrecedenceAnd(pattern) {
1568
+ for (let index = 0; index < pattern.length; index++) {
1569
+ if (IsOpenParen(pattern, index))
1570
+ return true;
1571
+ }
1572
+ return false;
1573
+ }
1574
+ function Or(pattern) {
1575
+ let [count, start] = [0, 0];
1576
+ const expressions = [];
1577
+ for (let index = 0; index < pattern.length; index++) {
1578
+ if (IsOpenParen(pattern, index))
1579
+ count += 1;
1580
+ if (IsCloseParen(pattern, index))
1581
+ count -= 1;
1582
+ if (IsSeparator(pattern, index) && count === 0) {
1583
+ const range = pattern.slice(start, index);
1584
+ if (range.length > 0)
1585
+ expressions.push(Parse(range));
1586
+ start = index + 1;
1587
+ }
1588
+ }
1589
+ const range = pattern.slice(start);
1590
+ if (range.length > 0)
1591
+ expressions.push(Parse(range));
1592
+ if (expressions.length === 0)
1593
+ return { type: 'const', const: '' };
1594
+ if (expressions.length === 1)
1595
+ return expressions[0];
1596
+ return { type: 'or', expr: expressions };
1597
+ }
1598
+ function And(pattern) {
1599
+ function Group(value, index) {
1600
+ if (!IsOpenParen(value, index))
1601
+ throw new TemplateLiteralParserError(`TemplateLiteralParser: Index must point to open parens`);
1602
+ let count = 0;
1603
+ for (let scan = index; scan < value.length; scan++) {
1604
+ if (IsOpenParen(value, scan))
1605
+ count += 1;
1606
+ if (IsCloseParen(value, scan))
1607
+ count -= 1;
1608
+ if (count === 0)
1609
+ return [index, scan];
1610
+ }
1611
+ throw new TemplateLiteralParserError(`TemplateLiteralParser: Unclosed group parens in expression`);
1612
+ }
1613
+ function Range(pattern, index) {
1614
+ for (let scan = index; scan < pattern.length; scan++) {
1615
+ if (IsOpenParen(pattern, scan))
1616
+ return [index, scan];
1617
+ }
1618
+ return [index, pattern.length];
1619
+ }
1620
+ const expressions = [];
1621
+ for (let index = 0; index < pattern.length; index++) {
1622
+ if (IsOpenParen(pattern, index)) {
1623
+ const [start, end] = Group(pattern, index);
1624
+ const range = pattern.slice(start, end + 1);
1625
+ expressions.push(Parse(range));
1626
+ index = end;
1627
+ }
1628
+ else {
1629
+ const [start, end] = Range(pattern, index);
1630
+ const range = pattern.slice(start, end);
1631
+ if (range.length > 0)
1632
+ expressions.push(Parse(range));
1633
+ index = end - 1;
1634
+ }
1635
+ }
1636
+ if (expressions.length === 0)
1637
+ return { type: 'const', const: '' };
1638
+ if (expressions.length === 1)
1639
+ return expressions[0];
1640
+ return { type: 'and', expr: expressions };
1641
+ }
1642
+ /** Parses a pattern and returns an expression tree */
1643
+ function Parse(pattern) {
1644
+ if (IsGroup(pattern))
1645
+ return Parse(InGroup(pattern));
1646
+ if (IsPrecedenceOr(pattern))
1647
+ return Or(pattern);
1648
+ if (IsPrecedenceAnd(pattern))
1649
+ return And(pattern);
1650
+ return { type: 'const', const: Unescape(pattern) };
1651
+ }
1652
+ TemplateLiteralParser.Parse = Parse;
1653
+ /** Parses a pattern and strips forward and trailing ^ and $ */
1654
+ function ParseExact(pattern) {
1655
+ return Parse(pattern.slice(1, pattern.length - 1));
1656
+ }
1657
+ TemplateLiteralParser.ParseExact = ParseExact;
1658
+ })(TemplateLiteralParser = exports.TemplateLiteralParser || (exports.TemplateLiteralParser = {}));
1659
+ // --------------------------------------------------------------------------------------
1660
+ // TemplateLiteralFinite
1661
+ // --------------------------------------------------------------------------------------
1662
+ var TemplateLiteralFinite;
1663
+ (function (TemplateLiteralFinite) {
1664
+ function IsNumber(expression) {
1665
+ return expression.type === 'or' && expression.expr.length === 2 && expression.expr[0].type === 'const' && expression.expr[0].const === '0' && expression.expr[1].type === 'const' && expression.expr[1].const === '[1-9][0-9]*';
1666
+ }
1667
+ function IsBoolean(expression) {
1668
+ return expression.type === 'or' && expression.expr.length === 2 && expression.expr[0].type === 'const' && expression.expr[0].const === 'true' && expression.expr[1].type === 'const' && expression.expr[1].const === 'false';
1669
+ }
1670
+ function IsString(expression) {
1671
+ return expression.type === 'const' && expression.const === '.*';
1672
+ }
1673
+ function Check(expression) {
1674
+ if (IsBoolean(expression))
1675
+ return true;
1676
+ if (IsNumber(expression) || IsString(expression))
1677
+ return false;
1678
+ if (expression.type === 'and')
1679
+ return expression.expr.every((expr) => Check(expr));
1680
+ if (expression.type === 'or')
1681
+ return expression.expr.every((expr) => Check(expr));
1682
+ if (expression.type === 'const')
1683
+ return true;
1684
+ throw Error(`TemplateLiteralFinite: Unknown expression type`);
1685
+ }
1686
+ TemplateLiteralFinite.Check = Check;
1687
+ })(TemplateLiteralFinite = exports.TemplateLiteralFinite || (exports.TemplateLiteralFinite = {}));
1688
+ // --------------------------------------------------------------------------------------
1689
+ // TemplateLiteralGenerator
1690
+ // --------------------------------------------------------------------------------------
1691
+ var TemplateLiteralGenerator;
1692
+ (function (TemplateLiteralGenerator) {
1693
+ function* Reduce(buffer) {
1694
+ if (buffer.length === 1)
1695
+ return yield* buffer[0];
1696
+ for (const left of buffer[0]) {
1697
+ for (const right of Reduce(buffer.slice(1))) {
1698
+ yield `${left}${right}`;
1699
+ }
1700
+ }
1701
+ }
1702
+ function* And(expression) {
1703
+ return yield* Reduce(expression.expr.map((expr) => [...Generate(expr)]));
1704
+ }
1705
+ function* Or(expression) {
1706
+ for (const expr of expression.expr)
1707
+ yield* Generate(expr);
1708
+ }
1709
+ function* Const(expression) {
1710
+ return yield expression.const;
1711
+ }
1712
+ function* Generate(expression) {
1713
+ if (expression.type === 'and')
1714
+ return yield* And(expression);
1715
+ if (expression.type === 'or')
1716
+ return yield* Or(expression);
1717
+ if (expression.type === 'const')
1718
+ return yield* Const(expression);
1719
+ throw Error('TemplateLiteralGenerator: Unknown expression');
1720
+ }
1721
+ TemplateLiteralGenerator.Generate = Generate;
1722
+ })(TemplateLiteralGenerator = exports.TemplateLiteralGenerator || (exports.TemplateLiteralGenerator = {}));
1723
+ // --------------------------------------------------------------------------
1425
1724
  // TypeOrdinal: Used for auto $id generation
1426
1725
  // --------------------------------------------------------------------------
1427
1726
  let TypeOrdinal = 0;
@@ -1536,6 +1835,10 @@ class StandardTypeBuilder extends TypeBuilder {
1536
1835
  }
1537
1836
  /** `[Standard]` Excludes from the left type any type that is not assignable to the right */
1538
1837
  Exclude(left, right, options = {}) {
1838
+ if (TypeGuard.TTemplateLiteral(left))
1839
+ return this.Exclude(TemplateLiteralResolver.Resolve(left), right, options);
1840
+ if (TypeGuard.TTemplateLiteral(right))
1841
+ return this.Exclude(left, TemplateLiteralResolver.Resolve(right), options);
1539
1842
  if (TypeGuard.TUnion(left)) {
1540
1843
  const narrowed = left.anyOf.filter((inner) => TypeExtends.Extends(inner, right) === TypeExtendsResult.False);
1541
1844
  return (narrowed.length === 1 ? TypeClone.Clone(narrowed[0], options) : this.Union(narrowed, options));
@@ -1546,6 +1849,10 @@ class StandardTypeBuilder extends TypeBuilder {
1546
1849
  }
1547
1850
  /** `[Standard]` Extracts from the left type any type that is assignable to the right */
1548
1851
  Extract(left, right, options = {}) {
1852
+ if (TypeGuard.TTemplateLiteral(left))
1853
+ return this.Extract(TemplateLiteralResolver.Resolve(left), right, options);
1854
+ if (TypeGuard.TTemplateLiteral(right))
1855
+ return this.Extract(left, TemplateLiteralResolver.Resolve(right), options);
1549
1856
  if (TypeGuard.TUnion(left)) {
1550
1857
  const narrowed = left.anyOf.filter((inner) => TypeExtends.Extends(inner, right) !== TypeExtendsResult.False);
1551
1858
  return (narrowed.length === 1 ? TypeClone.Clone(narrowed[0], options) : this.Union(narrowed, options));
@@ -1575,10 +1882,21 @@ class StandardTypeBuilder extends TypeBuilder {
1575
1882
  }
1576
1883
  /** `[Standard]` Creates a KeyOf type */
1577
1884
  KeyOf(schema, options = {}) {
1578
- const keys = KeyResolver.Resolve(schema);
1579
- // prettier-ignore
1580
- const keyof = keys.length === 0 ? this.Never(options) : this.Union(keys.map((key) => this.Literal(key)), options);
1581
- return keyof;
1885
+ if (TypeGuard.TRecord(schema)) {
1886
+ const pattern = Object.getOwnPropertyNames(schema.patternProperties)[0];
1887
+ if (pattern === exports.PatternNumberExact)
1888
+ return this.Number(options);
1889
+ if (pattern === exports.PatternStringExact)
1890
+ return this.String(options);
1891
+ throw Error('StandardTypeBuilder: Unable to resolve key type from Record key pattern');
1892
+ }
1893
+ else {
1894
+ const resolved = KeyResolver.Resolve(schema);
1895
+ if (resolved.length === 0)
1896
+ return this.Never(options);
1897
+ const literals = resolved.map((key) => this.Literal(key));
1898
+ return this.Union(literals, options);
1899
+ }
1582
1900
  }
1583
1901
  /** `[Standard]` Creates a Literal type */
1584
1902
  Literal(value, options = {}) {
@@ -1680,15 +1998,16 @@ class StandardTypeBuilder extends TypeBuilder {
1680
1998
  return this.Create(schema);
1681
1999
  }, options);
1682
2000
  }
2001
+ /** `[Standard]` Creates a Record type */
1683
2002
  Record(key, schema, options = {}) {
1684
- if (TypeGuard.TLiteral(key)) {
1685
- if (typeof key.const === 'string' || typeof key.const === 'number') {
1686
- return this.Object({ [key.const]: TypeClone.Clone(schema, {}) }, options);
1687
- }
1688
- else
1689
- throw Error('TypeBuilder: Record key can only be derived from literals of number or string');
2003
+ if (TypeGuard.TTemplateLiteral(key)) {
2004
+ const expression = TemplateLiteralParser.ParseExact(key.pattern);
2005
+ // prettier-ignore
2006
+ return TemplateLiteralFinite.Check(expression)
2007
+ ? (this.Object([...TemplateLiteralGenerator.Generate(expression)].reduce((acc, key) => ({ ...acc, [key]: TypeClone.Clone(schema, {}) }), {}), options))
2008
+ : this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [key.pattern]: TypeClone.Clone(schema, {}) }, additionalProperties: false });
1690
2009
  }
1691
- if (TypeGuard.TUnion(key)) {
2010
+ else if (TypeGuard.TUnionLiteral(key)) {
1692
2011
  if (key.anyOf.every((schema) => TypeGuard.TLiteral(schema) && (typeof schema.const === 'string' || typeof schema.const === 'number'))) {
1693
2012
  const properties = key.anyOf.reduce((acc, literal) => ({ ...acc, [literal.const]: TypeClone.Clone(schema, {}) }), {});
1694
2013
  return this.Object(properties, { ...options, [exports.Hint]: 'Record' });
@@ -1696,22 +2015,32 @@ class StandardTypeBuilder extends TypeBuilder {
1696
2015
  else
1697
2016
  throw Error('TypeBuilder: Record key can only be derived from union literal of number or string');
1698
2017
  }
1699
- const pattern = ['Integer', 'Number'].includes(key[exports.Kind]) ? '^(0|[1-9][0-9]*)$' : key[exports.Kind] === 'String' && key.pattern ? key.pattern : '^.*$';
1700
- return this.Create({
1701
- ...options,
1702
- [exports.Kind]: 'Record',
1703
- type: 'object',
1704
- patternProperties: { [pattern]: TypeClone.Clone(schema, {}) },
1705
- additionalProperties: false,
1706
- });
2018
+ else if (TypeGuard.TLiteral(key)) {
2019
+ if (typeof key.const === 'string' || typeof key.const === 'number') {
2020
+ return this.Object({ [key.const]: TypeClone.Clone(schema, {}) }, options);
2021
+ }
2022
+ else
2023
+ throw Error('TypeBuilder: Record key can only be derived from literals of number or string');
2024
+ }
2025
+ else if (TypeGuard.TInteger(key) || TypeGuard.TNumber(key)) {
2026
+ const pattern = exports.PatternNumberExact;
2027
+ return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Clone(schema, {}) }, additionalProperties: false });
2028
+ }
2029
+ else if (TypeGuard.TString(key)) {
2030
+ const pattern = key.pattern === undefined ? exports.PatternStringExact : key.pattern;
2031
+ return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Clone(schema, {}) }, additionalProperties: false });
2032
+ }
2033
+ else {
2034
+ throw Error(`StandardTypeBuilder: Invalid Record Key`);
2035
+ }
1707
2036
  }
1708
2037
  /** `[Standard]` Creates a Recursive type */
1709
2038
  Recursive(callback, options = {}) {
1710
2039
  if (options.$id === undefined)
1711
2040
  options.$id = `T${TypeOrdinal++}`;
1712
- const self = callback({ [exports.Kind]: 'Self', $ref: `${options.$id}` });
1713
- self.$id = options.$id;
1714
- return this.Create({ ...options, ...self });
2041
+ const thisType = callback({ [exports.Kind]: 'This', $ref: `${options.$id}` });
2042
+ thisType.$id = options.$id;
2043
+ return this.Create({ ...options, ...thisType });
1715
2044
  }
1716
2045
  /** `[Standard]` Creates a Ref type. The referenced type must contain a $id */
1717
2046
  Ref(schema, options = {}) {
@@ -1749,6 +2078,11 @@ class StandardTypeBuilder extends TypeBuilder {
1749
2078
  String(options = {}) {
1750
2079
  return this.Create({ ...options, [exports.Kind]: 'String', type: 'string' });
1751
2080
  }
2081
+ /** `[Standard]` Creates a template literal type */
2082
+ TemplateLiteral(kinds, options = {}) {
2083
+ const pattern = TemplateLiteralPattern.Create(kinds);
2084
+ return this.Create({ ...options, [exports.Kind]: 'TemplateLiteral', type: 'string', pattern });
2085
+ }
1752
2086
  /** `[Standard]` Creates a Tuple type */
1753
2087
  Tuple(items, options = {}) {
1754
2088
  const [additionalItems, minItems, maxItems] = [false, items.length, items.length];
@@ -1759,13 +2093,19 @@ class StandardTypeBuilder extends TypeBuilder {
1759
2093
  { ...options, [exports.Kind]: 'Tuple', type: 'array', minItems, maxItems });
1760
2094
  return this.Create(schema);
1761
2095
  }
1762
- Union(anyOf, options = {}) {
1763
- if (anyOf.length === 0)
1764
- return this.Never(options);
1765
- if (anyOf.length === 1)
1766
- return this.Create(TypeClone.Clone(anyOf[0], options));
1767
- const clonedAnyOf = anyOf.map((schema) => TypeClone.Clone(schema, {}));
1768
- return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: clonedAnyOf });
2096
+ Union(union, options = {}) {
2097
+ if (TypeGuard.TTemplateLiteral(union)) {
2098
+ return TemplateLiteralResolver.Resolve(union);
2099
+ }
2100
+ else {
2101
+ const anyOf = union;
2102
+ if (anyOf.length === 0)
2103
+ return this.Never(options);
2104
+ if (anyOf.length === 1)
2105
+ return this.Create(TypeClone.Clone(anyOf[0], options));
2106
+ const clonedAnyOf = anyOf.map((schema) => TypeClone.Clone(schema, {}));
2107
+ return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: clonedAnyOf });
2108
+ }
1769
2109
  }
1770
2110
  /** `[Standard]` Creates an Unknown type */
1771
2111
  Unknown(options = {}) {
@@ -1778,7 +2118,7 @@ class StandardTypeBuilder extends TypeBuilder {
1778
2118
  }
1779
2119
  exports.StandardTypeBuilder = StandardTypeBuilder;
1780
2120
  // --------------------------------------------------------------------------
1781
- // TypeBuilder
2121
+ // ExtendedTypeBuilder
1782
2122
  // --------------------------------------------------------------------------
1783
2123
  class ExtendedTypeBuilder extends StandardTypeBuilder {
1784
2124
  /** `[Extended]` Creates a BigInt type */
package/value/cast.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as Types from '../typebox';
2
2
  export declare class ValueCastReferenceTypeError extends Error {
3
- readonly schema: Types.TRef | Types.TSelf;
4
- constructor(schema: Types.TRef | Types.TSelf);
3
+ readonly schema: Types.TRef | Types.TThis;
4
+ constructor(schema: Types.TRef | Types.TThis);
5
5
  }
6
6
  export declare class ValueCastArrayUniqueItemsTypeError extends Error {
7
7
  readonly schema: Types.TSchema;
@@ -21,8 +21,8 @@ export declare class ValueCastUnknownTypeError extends Error {
21
21
  constructor(schema: Types.TSchema);
22
22
  }
23
23
  export declare class ValueCastDereferenceError extends Error {
24
- readonly schema: Types.TRef | Types.TSelf;
25
- constructor(schema: Types.TRef | Types.TSelf);
24
+ readonly schema: Types.TRef | Types.TThis;
25
+ constructor(schema: Types.TRef | Types.TThis);
26
26
  }
27
27
  export declare namespace ValueCast {
28
28
  function Visit(schema: Types.TSchema, references: Types.TSchema[], value: any): any;
package/value/cast.js CHANGED
@@ -255,19 +255,22 @@ var ValueCast;
255
255
  const target = references[index];
256
256
  return Visit(target, references, value);
257
257
  }
258
- function Self(schema, references, value) {
259
- const index = references.findIndex((foreign) => foreign.$id === schema.$ref);
260
- if (index === -1)
261
- throw new ValueCastDereferenceError(schema);
262
- const target = references[index];
263
- return Visit(target, references, value);
264
- }
265
258
  function String(schema, references, value) {
266
259
  return check_1.ValueCheck.Check(schema, references, value) ? value : create_1.ValueCreate.Create(schema, references);
267
260
  }
268
261
  function Symbol(schema, references, value) {
269
262
  return check_1.ValueCheck.Check(schema, references, value) ? clone_1.ValueClone.Clone(value) : create_1.ValueCreate.Create(schema, references);
270
263
  }
264
+ function TemplateLiteral(schema, references, value) {
265
+ return check_1.ValueCheck.Check(schema, references, value) ? clone_1.ValueClone.Clone(value) : create_1.ValueCreate.Create(schema, references);
266
+ }
267
+ function This(schema, references, value) {
268
+ const index = references.findIndex((foreign) => foreign.$id === schema.$ref);
269
+ if (index === -1)
270
+ throw new ValueCastDereferenceError(schema);
271
+ const target = references[index];
272
+ return Visit(target, references, value);
273
+ }
271
274
  function Tuple(schema, references, value) {
272
275
  if (check_1.ValueCheck.Check(schema, references, value))
273
276
  return clone_1.ValueClone.Clone(value);
@@ -335,12 +338,14 @@ var ValueCast;
335
338
  return Record(schema_, references_, value);
336
339
  case 'Ref':
337
340
  return Ref(schema_, references_, value);
338
- case 'Self':
339
- return Self(schema_, references_, value);
340
341
  case 'String':
341
342
  return String(schema_, references_, value);
342
343
  case 'Symbol':
343
344
  return Symbol(schema_, references_, value);
345
+ case 'TemplateLiteral':
346
+ return TemplateLiteral(schema_, references_, value);
347
+ case 'This':
348
+ return This(schema_, references_, value);
344
349
  case 'Tuple':
345
350
  return Tuple(schema_, references_, value);
346
351
  case 'Undefined':
package/value/check.d.ts CHANGED
@@ -4,8 +4,8 @@ export declare class ValueCheckUnknownTypeError extends Error {
4
4
  constructor(schema: Types.TSchema);
5
5
  }
6
6
  export declare class ValueCheckDereferenceError extends Error {
7
- readonly schema: Types.TRef | Types.TSelf;
8
- constructor(schema: Types.TRef | Types.TSelf);
7
+ readonly schema: Types.TRef | Types.TThis;
8
+ constructor(schema: Types.TRef | Types.TThis);
9
9
  }
10
10
  export declare namespace ValueCheck {
11
11
  function Check<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: any): boolean;