@evolu/common 8.1.0 → 8.2.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.
@@ -10,7 +10,7 @@ import type { RandomBytesDep } from "./Crypto.ts";
10
10
  import { type Thunk } from "./Function.ts";
11
11
  import { type Result } from "./Result.ts";
12
12
  import type { TimeDep } from "./Time.ts";
13
- import { type CompileTimeError, type Digit, type Digit1To9, type Int1To100, type IsUnion, type Literal, type Simplify, type ValueWithLength, type WidenLiteral } from "./Types.ts";
13
+ import { type CompileTimeError, type IsUnion, type Literal, type Simplify, type ValueWithLength, type WidenLiteral } from "./Types.ts";
14
14
  /**
15
15
  * A runtime representation of a TypeScript type with typed structured errors.
16
16
  *
@@ -108,8 +108,8 @@ import { type CompileTimeError, type Digit, type Digit1To9, type Int1To100, type
108
108
  * normalized value, it uses a `null` prototype so every string key remains
109
109
  * ordinary data.
110
110
  *
111
- * Evolu Type expects TypeScript's `exactOptionalPropertyTypes` compiler option
112
- * to be enabled.
111
+ * Evolu Type requires TypeScript 7 or newer and expects the
112
+ * `exactOptionalPropertyTypes` compiler option to be enabled.
113
113
  *
114
114
  * Predefined Types intentionally use the names of corresponding JavaScript
115
115
  * built-ins because they represent those familiar value categories. If an
@@ -625,7 +625,7 @@ export interface TypeNode {
625
625
  */
626
626
  export declare const assertType: <T extends TypeNode>(type: T, value: unknown) => asserts value is T["Output"];
627
627
  /**
628
- * Creates localized copies of selected {@link Type | Types} for every locale.
628
+ * Localized copies of selected {@link Type} declarations for every locale.
629
629
  *
630
630
  * Each locale supplies one formatter for every Type that can own a formatted
631
631
  * error. Structural Types use their own formatter for structural failures and
@@ -988,6 +988,8 @@ type DeepestFromError<Operation> = DeepestFromOperation<Operation> extends (...a
988
988
  readonly error: infer Error extends TypeError;
989
989
  } ? Error : never : never;
990
990
  type TypeFromError<T extends TypeNode> = unknown extends T[typeof customFromSymbol] ? DeepestFromError<TypeFromOperation<T>> : [T[typeof customFromSymbol]] extends [never] ? NonRootErrors<T> : DeepestFromError<T[typeof customFromSymbol]>;
991
+ declare const templateLiteralSyntaxSymbolType: unique symbol;
992
+ declare const templateLiteralSyntaxSymbol: typeof templateLiteralSyntaxSymbolType;
991
993
  /** @group Base Types */
992
994
  export declare const Unknown: Type<"Unknown", unknown, unknown, never, null, never, never, unknown, true>;
993
995
  /** @group Base Types */
@@ -1178,7 +1180,7 @@ interface ObjectTagOutputByName {
1178
1180
  readonly ArrayBuffer: globalThis.ArrayBuffer;
1179
1181
  }
1180
1182
  /**
1181
- * Creates a realm-neutral {@link Type} that trusts an object's reported tag.
1183
+ * Realm-neutral {@link Type} trusting an object's reported tag.
1182
1184
  *
1183
1185
  * Predefined built-in tags expose their native Output type under the assumption
1184
1186
  * that trusted code does not forge their tags. They do not verify native
@@ -1227,7 +1229,7 @@ export declare const Uint8Array: Type<"Uint8Array", Uint8Array<ArrayBufferLike>,
1227
1229
  */
1228
1230
  export declare const ArrayBuffer: Type<"ArrayBuffer", ArrayBuffer, ArrayBuffer, ObjectTagError<"ArrayBuffer">, null, ObjectTagError<"ArrayBuffer">, never, ArrayBuffer, true>;
1229
1231
  /**
1230
- * Creates a {@link Type} for instances of one constructor.
1232
+ * Instance {@link Type} for one constructor.
1231
1233
  *
1232
1234
  * Membership uses the intrinsic prototype chain, so subclasses are accepted,
1233
1235
  * equivalent constructors from other realms are rejected, and custom
@@ -1286,11 +1288,32 @@ type InstanceConstructorCompileTimeError = CompileTimeError<"Type", "Constructor
1286
1288
  * primitive through `from.parent`. The expected value must have one exact
1287
1289
  * literal type. Validation uses `===`, so `-0` matches `0`.
1288
1290
  *
1291
+ * In {@link templateLiteralParser}, use a string Literal Type when the literal
1292
+ * should be decoded into the Output Tuple. Use a raw string when it should only
1293
+ * frame the canonical string.
1294
+ *
1295
+ * ### Example
1296
+ *
1297
+ * ```ts
1298
+ * import { literal } from "@evolu/common";
1299
+ *
1300
+ * const Ready = literal("ready");
1301
+ *
1302
+ * expectTypeOf<typeof Ready.Output>().toEqualTypeOf<"ready">();
1303
+ * expectOk(Ready.fromUnknown("ready"), "ready");
1304
+ * expectErr(Ready.fromUnknown("pending"), {
1305
+ * type: "Literal",
1306
+ * expected: "ready",
1307
+ * value: "pending",
1308
+ * });
1309
+ * ```
1310
+ *
1289
1311
  * @group Unions
1290
1312
  */
1291
1313
  export declare const literal: <const Expected extends Literal>(expected: ValidateLiteral<Expected>) => LiteralType<Expected>;
1292
1314
  /** @group Unions */
1293
1315
  export interface LiteralType<Expected extends Literal> extends Type<"Literal", WidenLiteral<Expected>, Expected, LiteralError<Expected>, LiteralParent<Expected>, LiteralError<Expected> | LiteralParentErrors<Expected>, never, CanonicalInputSubset<WidenLiteral<Expected>, CanonicalInputForParent<LiteralParent<Expected>, Expected>>, IdentityEncodingForParent<LiteralParent<Expected>>> {
1316
+ readonly [templateLiteralSyntaxSymbol]: true;
1294
1317
  readonly expected: Expected;
1295
1318
  }
1296
1319
  type LiteralParent<Expected extends Literal> = Expected extends string ? typeof String : Expected extends number ? typeof Number : Expected extends bigint ? typeof BigInt : Expected extends boolean ? typeof Boolean : null;
@@ -1373,7 +1396,7 @@ export declare function union<const Members extends AtLeastTwoReadonlyArray<Type
1373
1396
  readonly [Index in keyof Members]: ValidateUnionMember<Members[Index]>;
1374
1397
  }): UnionType<NormalizeUnionMembers<Members>>;
1375
1398
  /**
1376
- * Shorthand for passing a {@link Type} and `undefined` to {@link union}.
1399
+ * Union {@link Type} containing the supplied Type and `undefined`.
1377
1400
  *
1378
1401
  * This does not make an object property optional. It changes only the values
1379
1402
  * accepted when the property is present.
@@ -1382,13 +1405,13 @@ export declare function union<const Members extends AtLeastTwoReadonlyArray<Type
1382
1405
  */
1383
1406
  export declare const undefinedOr: <ValueType extends TypeNode>(type: ValidateUnionTypeMember<ValueType>) => UnionType<readonly [ValueType, typeof Undefined]>;
1384
1407
  /**
1385
- * Shorthand for passing a {@link Type} and `null` to {@link union}.
1408
+ * Union {@link Type} containing the supplied Type and `null`.
1386
1409
  *
1387
1410
  * @group Unions
1388
1411
  */
1389
1412
  export declare const nullOr: <ValueType extends TypeNode>(type: ValidateUnionTypeMember<ValueType>) => UnionType<readonly [ValueType, typeof Null]>;
1390
1413
  /**
1391
- * Shorthand for passing a {@link Type}, `null`, and `undefined` to {@link union}.
1414
+ * Union {@link Type} containing the supplied Type, `null`, and `undefined`.
1392
1415
  *
1393
1416
  * @group Unions
1394
1417
  */
@@ -1403,6 +1426,7 @@ type NormalizeUnionMembers<Members extends AtLeastTwoReadonlyArray<TypeNode | Li
1403
1426
  } extends infer Normalized extends AtLeastTwoReadonlyArray<TypeNode> ? Normalized : never;
1404
1427
  /** @group Unions */
1405
1428
  export interface UnionType<Members extends AtLeastTwoReadonlyArray<TypeNode>> extends Type<"Union", Members[number]["Input"], Members[number]["Output"], UnionTypeError<Members>, UnionInputParent<Members>, UnionTypeError<Members>, never, CanonicalInputOf<Members[number]>, AllTypesUseIdentityEncoding<Members[number]>> {
1429
+ readonly [templateLiteralSyntaxSymbol]: true;
1406
1430
  readonly [reflectedTypesSymbol]?: Members[number];
1407
1431
  readonly members: Members;
1408
1432
  }
@@ -1447,6 +1471,256 @@ type InfallibleTypeNode = TypeNode & {
1447
1471
  interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemberError<Error> = UnionMemberError<Error>> extends TypeError<"Union"> {
1448
1472
  readonly errors: NonEmptyReadonlyArray<MemberError>;
1449
1473
  }
1474
+ /**
1475
+ * Template literal {@link Type} for validation and parsing.
1476
+ *
1477
+ * Parses and creates structured strings.
1478
+ *
1479
+ * Accepts the same template parts as {@link templateLiteral}: fixed string
1480
+ * literals and Types canonically encoded as strings. Instead of keeping Output
1481
+ * as a string, fixed literals define the framing and Output is a readonly Tuple
1482
+ * of the decoded Type parts. `to` encodes that Tuple back into the canonical
1483
+ * string represented by the parent Type. At least one Type part is required.
1484
+ *
1485
+ * When every capture uses identity encoding, the parent Output is the exact
1486
+ * TypeScript template literal type. A transforming capture makes it nominal;
1487
+ * create such strings with `to` or validate them with the parent Type.
1488
+ *
1489
+ * Deterministic framing is a core correctness guarantee. It preserves
1490
+ * reversibility and keeps capture boundaries unambiguous. Different capture
1491
+ * Tuples must never encode to the same string. The parser provides predictable
1492
+ * parsing without pathological backtracking and decodes each capture once, so
1493
+ * adversarial input cannot trigger exponential parser work. Fixed-width captures
1494
+ * may be adjacent, but only one variable-width capture is allowed. Declarations
1495
+ * that could join UTF-16 surrogate halves across parts are rejected during
1496
+ * construction.
1497
+ *
1498
+ * Keep capture unions reasonably small to avoid excessive compiler work.
1499
+ *
1500
+ * TypeScript template literal types can describe a fixed number of digit
1501
+ * positions, but not an arbitrarily long sequence of digits. Such grammars use
1502
+ * branded Types such as {@link DecimalString}; `templateLiteralParser` preserves
1503
+ * that exactness by requiring a validated branded capture when encoding.
1504
+ *
1505
+ * ### Example
1506
+ *
1507
+ * A template literal Type defines both a canonical string representation and
1508
+ * the structured data decoded from it:
1509
+ *
1510
+ * ```ts
1511
+ * import { templateLiteralParser, union } from "@evolu/common";
1512
+ *
1513
+ * const Language = union("en", "cs");
1514
+ * const Region = union("US", "CZ");
1515
+ *
1516
+ * // Define a Type for "en-US" | "en-CZ" | "cs-US" | "cs-CZ".
1517
+ * const SupportedLocale = templateLiteralParser(Language, "-", Region);
1518
+ *
1519
+ * // Output is the decoded language and region.
1520
+ * type SupportedLocale = typeof SupportedLocale.Output;
1521
+ * expectTypeOf<SupportedLocale>().toEqualTypeOf<
1522
+ * readonly ["en" | "cs", "US" | "CZ"]
1523
+ * >();
1524
+ *
1525
+ * // The parent Output is the canonical locale string.
1526
+ * type SupportedLocaleLiteral = typeof SupportedLocale.parent.Output;
1527
+ * expectTypeOf<SupportedLocaleLiteral>().toEqualTypeOf<
1528
+ * "en-US" | "en-CZ" | "cs-US" | "cs-CZ"
1529
+ * >();
1530
+ *
1531
+ * // Parse an unknown string into structured data.
1532
+ * const result = SupportedLocale.fromUnknown("cs-CZ");
1533
+ * assert(result.ok);
1534
+ * const locale = result.value;
1535
+ * expectTypeOf(locale).toEqualTypeOf<SupportedLocale>();
1536
+ * expect(locale).toEqual(["cs", "CZ"]);
1537
+ * expectErr(SupportedLocale.fromUnknown("cs/CZ"), {
1538
+ * type: "TemplateLiteral",
1539
+ * value: "cs/CZ",
1540
+ * });
1541
+ *
1542
+ * // Encode structured data into its canonical string.
1543
+ * const localeLiteral = SupportedLocale.to(locale);
1544
+ * expectTypeOf(localeLiteral).toEqualTypeOf<SupportedLocaleLiteral>();
1545
+ * expect(localeLiteral).toBe("cs-CZ");
1546
+ *
1547
+ * // Validate a string configuration value.
1548
+ * const configValue: unknown = "cs-CZ";
1549
+ * assert(SupportedLocale.parent.is(configValue));
1550
+ * expectTypeOf(configValue).toEqualTypeOf<SupportedLocaleLiteral>();
1551
+ * expect(SupportedLocale.parent.is("fr-CZ")).toBe(false);
1552
+ * ```
1553
+ *
1554
+ * `SupportedLocale` is structured data for application code.
1555
+ * `SupportedLocaleLiteral` is its canonical representation for configuration
1556
+ * and other APIs that require a string, such as URL parameters, environment
1557
+ * variables, and storage keys.
1558
+ *
1559
+ * Use branded captures for strings that TypeScript template literal types
1560
+ * cannot express exactly, such as arbitrary-length canonical decimals:
1561
+ *
1562
+ * ```ts
1563
+ * import {
1564
+ * NonNegativeDecimalString,
1565
+ * templateLiteralParser,
1566
+ * } from "@evolu/common";
1567
+ *
1568
+ * const DecimalText = templateLiteralParser(
1569
+ * "decimal:",
1570
+ * NonNegativeDecimalString,
1571
+ * );
1572
+ *
1573
+ * // DecimalText.to requires a validated NonNegativeDecimalString.
1574
+ * const zero = NonNegativeDecimalString.orThrow("0");
1575
+ *
1576
+ * expectOk(DecimalText.fromUnknown("decimal:0"), [zero]);
1577
+ * expect(DecimalText.to([zero])).toBe("decimal:0");
1578
+ * ```
1579
+ *
1580
+ * Capture Types (the Type arguments passed to `templateLiteralParser`) can use
1581
+ * transformations to decode substrings into non-string data:
1582
+ *
1583
+ * ```ts
1584
+ * import {
1585
+ * Int64FromInt64String,
1586
+ * templateLiteralParser,
1587
+ * } from "@evolu/common";
1588
+ *
1589
+ * const ItemId = templateLiteralParser("item-", Int64FromInt64String);
1590
+ * type ItemId = typeof ItemId.Output;
1591
+ * type ItemIdLiteral = typeof ItemId.parent.Output;
1592
+ *
1593
+ * // Decode the string into structured data.
1594
+ * const result = ItemId.fromUnknown("item-42");
1595
+ * assert(result.ok);
1596
+ * const itemId = result.value;
1597
+ * expectTypeOf(itemId).toEqualTypeOf<ItemId>();
1598
+ * expect(itemId).toEqual([42n]);
1599
+ *
1600
+ * // Encode the structured data into its canonical string.
1601
+ * const itemIdLiteral = ItemId.to(itemId);
1602
+ * expectTypeOf(itemIdLiteral).toEqualTypeOf<ItemIdLiteral>();
1603
+ * expect(itemIdLiteral).toBe("item-42");
1604
+ *
1605
+ * // TypeScript cannot prove from the literal alone that "42" is a valid Int64 encoding.
1606
+ * // @ts-expect-error Validate it with ItemId.parent or create it with ItemId.to.
1607
+ * const invalidItemIdLiteral: ItemIdLiteral = "item-42";
1608
+ * ```
1609
+ *
1610
+ * Fixed-width captures can be adjacent:
1611
+ *
1612
+ * ```ts
1613
+ * import { templateLiteralParser, union } from "@evolu/common";
1614
+ *
1615
+ * const Digit = union("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
1616
+ * const TwoDigits = templateLiteralParser(Digit, Digit);
1617
+ * type TwoDigits = typeof TwoDigits.Output;
1618
+ * type TwoDigitsLiteral = typeof TwoDigits.parent.Output;
1619
+ *
1620
+ * const twoDigits: TwoDigits = ["4", "2"];
1621
+ * const twoDigitsLiteral: TwoDigitsLiteral = "42";
1622
+ * // @ts-expect-error TwoDigitsLiteral requires exactly two digits.
1623
+ * const threeDigitsLiteral: TwoDigitsLiteral = "123";
1624
+ *
1625
+ * expectOk(TwoDigits.from.parent(twoDigitsLiteral), twoDigits);
1626
+ * expect(TwoDigits.to(twoDigits)).toBe(twoDigitsLiteral);
1627
+ * ```
1628
+ *
1629
+ * TypeScript rejects multiple variable-width captures because their encoded
1630
+ * boundaries would be ambiguous:
1631
+ *
1632
+ * ```ts
1633
+ * import { String, templateLiteralParser } from "@evolu/common";
1634
+ *
1635
+ * // @ts-expect-error At most one Type capture can have a variable-width string representation.
1636
+ * templateLiteralParser(String, ":", String);
1637
+ * ```
1638
+ *
1639
+ * This restriction keeps encoding reversible: different capture Tuples must
1640
+ * never produce the same string. A delimiter alone is not enough because it can
1641
+ * also occur inside a capture. Some formats could provide stronger guarantees,
1642
+ * such as captures that exclude a delimiter; support for those can be added
1643
+ * when concrete use cases justify the additional framing rules.
1644
+ *
1645
+ * @group Template literals
1646
+ */
1647
+ export declare const templateLiteralParser: <const Parts extends TemplateLiteralParts>(...parts: { readonly [Index in keyof Parts]: ValidateTemplateLiteralPart<Parts[Index]>; } & TemplateLiteralValidation<Parts>) => TemplateLiteralParserType<Parts>;
1648
+ /** @group Template literals */
1649
+ export interface TemplateLiteralParserType<Parts extends TemplateLiteralParts> extends Type<"TemplateLiteral", string, TemplateLiteralCaptureTuple<Parts>["Output"], never, TemplateLiteralType<Parts>, InferErrors<TemplateLiteralType<Parts>>, never, TemplateLiteralStringOutput<Parts>, false> {
1650
+ readonly [templateLiteralSyntaxSymbol]: true;
1651
+ readonly [reflectedTypesSymbol]?: TemplateLiteralCaptureTuple<Parts>;
1652
+ readonly output: TemplateLiteralCaptureTuple<Parts>;
1653
+ readonly parts: Parts;
1654
+ }
1655
+ /** @group Template literals */
1656
+ export interface TemplateLiteralType<Parts extends TemplateLiteralParts> extends Type<"TemplateLiteral", string, TemplateLiteralStringOutput<Parts>, TemplateLiteralParseError<Parts>, typeof String, TypeOfError<"String"> | TemplateLiteralParseError<Parts>, never, TemplateLiteralStringOutput<Parts>, true> {
1657
+ readonly [templateLiteralSyntaxSymbol]: true;
1658
+ readonly [reflectedTypesSymbol]?: TemplateLiteralCaptureTuple<Parts>;
1659
+ readonly output: TemplateLiteralCaptureTuple<Parts>;
1660
+ readonly parts: Parts;
1661
+ }
1662
+ /**
1663
+ * Template literal {@link Type} for validation.
1664
+ *
1665
+ * Creates a canonical string Type from fixed strings and string-encoded Types.
1666
+ *
1667
+ * Use this factory when Output should remain a string. Switch to
1668
+ * {@link templateLiteralParser} when the individual Type parts should be
1669
+ * decoded into a Tuple.
1670
+ *
1671
+ * ### Example
1672
+ *
1673
+ * ```ts
1674
+ * import { templateLiteral, union } from "@evolu/common";
1675
+ *
1676
+ * const Language = union("en", "cs");
1677
+ * const Region = union("US", "CZ");
1678
+ * const Locale = templateLiteral(Language, "-", Region);
1679
+ *
1680
+ * expectTypeOf<typeof Locale.Output>().toEqualTypeOf<
1681
+ * "en-US" | "en-CZ" | "cs-US" | "cs-CZ"
1682
+ * >();
1683
+ * expectOk(Locale.fromUnknown("cs-CZ"), "cs-CZ");
1684
+ * expect(Locale.is("fr-CZ")).toBe(false);
1685
+ * ```
1686
+ *
1687
+ * @group Template literals
1688
+ */
1689
+ export declare const templateLiteral: <const Parts extends TemplateLiteralParts>(...parts: { readonly [Index in keyof Parts]: ValidateTemplateLiteralPart<Parts[Index]>; } & TemplateLiteralValidation<Parts>) => TemplateLiteralType<Parts>;
1690
+ type TemplateLiteralParseError<Parts extends TemplateLiteralParts> = TransformError<"TemplateLiteral", TemplateLiteralIsFrameless<Parts> extends true ? never : TemplateLiteralError, TemplateLiteralCaptureTupleError<Parts>>;
1691
+ type TemplateLiteralCaptureTupleError<Parts extends TemplateLiteralParts> = TupleElementsError<TemplateLiteralCaptureFromStringError<TemplateLiteralCaptureTypes<Parts>[number]>>;
1692
+ type TemplateLiteralCaptureFromStringError<T extends TypeNode> = T extends TypeNode ? string extends RootType<T>["Output"] ? TypeFromError<T> : InferErrors<T> : never;
1693
+ /** @group Template literals */
1694
+ export interface TemplateLiteralError extends TypeError<"TemplateLiteral"> {
1695
+ readonly value: string;
1696
+ }
1697
+ declare const templateLiteralStringBrandSymbol: unique symbol;
1698
+ interface TemplateLiteralStringBrand<Parts extends TemplateLiteralParts> {
1699
+ readonly [templateLiteralStringBrandSymbol]: Parts;
1700
+ }
1701
+ type TemplateLiteralPart = string | TypeNode;
1702
+ type TemplateLiteralParts = NonEmptyReadonlyArray<TemplateLiteralPart>;
1703
+ type TemplateLiteralValidation<Parts extends TemplateLiteralParts> = number extends Parts["length"] ? readonly [ValidationFailure<TemplateLiteralPartsTupleError>] : IsUnion<Parts["length"]> extends true ? readonly [ValidationFailure<TemplateLiteralPartsTupleError>] : [Extract<Parts[number], TypeNode>] extends [never] ? readonly [ValidationFailure<TemplateLiteralCaptureRequiredError>] : TemplateLiteralHasAmbiguousCaptures<Parts> extends true ? readonly [ValidationFailure<TemplateLiteralAmbiguousCapturesError>] : unknown;
1704
+ type TemplateLiteralPartsTupleError = CompileTimeError<"TemplateLiteral", "Parts must use one concrete finite non-empty tuple.">;
1705
+ type TemplateLiteralCaptureRequiredError = CompileTimeError<"TemplateLiteral", "At least one part must be a Type capture.">;
1706
+ type TemplateLiteralAmbiguousCapturesError = CompileTimeError<"TemplateLiteral", "At most one Type capture can have a variable-width string representation.">;
1707
+ type TemplateLiteralCaptureTypes<Parts extends ReadonlyArray<TemplateLiteralPart>, Captures extends ReadonlyArray<TypeNode> = readonly []> = Parts extends readonly [infer Head, ...infer Tail] ? TemplateLiteralCaptureTypes<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, Head extends TypeNode ? readonly [...Captures, Head] : Captures> : Extract<Captures, NonEmptyReadonlyArray<TypeNode>>;
1708
+ type TemplateLiteralCaptureTuple<Parts extends TemplateLiteralParts> = TupleType<TemplateLiteralCaptureTypes<Parts>>;
1709
+ type TemplateLiteralCanonicalInput<Parts extends ReadonlyArray<TemplateLiteralPart>, Input extends string = ""> = Parts extends readonly [infer Head, ...infer Tail] ? TemplateLiteralCanonicalInput<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, `${Input}${TemplateLiteralPartCanonicalInput<Extract<Head, TemplateLiteralPart>>}`> : Input;
1710
+ type TemplateLiteralStringOutput<Parts extends TemplateLiteralParts> = AllTypesUseIdentityEncoding<Extract<Parts[number], TypeNode>> extends true ? TemplateLiteralCanonicalInput<Parts> : TemplateLiteralCanonicalInput<Parts> & TemplateLiteralStringBrand<Parts>;
1711
+ type TemplateLiteralPartCanonicalInput<Part extends TemplateLiteralPart> = Part extends string ? Part : Part extends TypeNode ? Extract<CanonicalInputOf<Part>, string> : never;
1712
+ type ValidateTemplateLiteralPart<Part extends TemplateLiteralPart> = IsUnion<Part> extends false ? Part extends string ? ValidateLiteral<Part> : Part extends ConcreteTypeNode ? IsTemplateLiteralPartType<Part> extends true ? Part : TemplateLiteralPartCompileTimeError : TemplateLiteralPartCompileTimeError : TemplateLiteralPartCompileTimeError;
1713
+ type IsTemplateLiteralPartType<T extends TypeNode> = [
1714
+ CanonicalInputOf<T>
1715
+ ] extends [never] ? false : [CanonicalInputOf<T>] extends [string] ? true : false;
1716
+ type TemplateLiteralPartCompileTimeError = CompileTimeError<"TemplateLiteral", "Part must be a raw string literal or a Type canonically encoded as a string.">;
1717
+ type TemplateLiteralHasAmbiguousCaptures<Parts extends ReadonlyArray<TemplateLiteralPart>, VariableCaptures extends ReadonlyArray<unknown> = readonly []> = Parts extends readonly [infer Head, ...infer Tail] ? Head extends TypeNode ? [TemplateLiteralTypeWidth<Head>] extends [null] ? VariableCaptures extends readonly [unknown] ? true : TemplateLiteralHasAmbiguousCaptures<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, readonly [unknown]> : TemplateLiteralHasAmbiguousCaptures<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, VariableCaptures> : TemplateLiteralHasAmbiguousCaptures<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, VariableCaptures> : false;
1718
+ type TemplateLiteralTypeWidth<T extends TypeNode> = T extends LiteralType<infer Expected extends string> ? TemplateLiteralStringWidth<Expected> : T extends UnionType<infer Members> ? NormalizeTemplateLiteralWidth<TemplateLiteralTypeWidth<Members[number]>> : T extends TemplateLiteralParserType<infer Parts> ? TemplateLiteralPartsWidth<Parts> : T extends TemplateLiteralType<infer Parts> ? TemplateLiteralPartsWidth<Parts> : T["parent"] extends infer Parent extends TypeNode ? TemplateLiteralTypeWidth<Parent> : null;
1719
+ type NormalizeTemplateLiteralWidth<Width> = IsUnion<Width> extends true ? null : Width extends ReadonlyArray<unknown> ? Width : null;
1720
+ type TemplateLiteralPartsWidth<Parts extends ReadonlyArray<TemplateLiteralPart>, Width extends ReadonlyArray<unknown> = readonly []> = Parts extends readonly [infer Head, ...infer Tail] ? TemplateLiteralPartWidth<Extract<Head, TemplateLiteralPart>> extends infer PartWidth ? [PartWidth] extends [ReadonlyArray<unknown>] ? TemplateLiteralPartsWidth<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, readonly [...Width, ...PartWidth]> : null : never : Width;
1721
+ type TemplateLiteralPartWidth<Part extends TemplateLiteralPart> = Part extends string ? TemplateLiteralStringWidth<Part> : Part extends TypeNode ? TemplateLiteralTypeWidth<Part> : never;
1722
+ type TemplateLiteralIsFrameless<Parts extends ReadonlyArray<TemplateLiteralPart>, HasVariableCapture extends boolean = false> = Parts extends readonly [infer Head, ...infer Tail] ? TemplateLiteralPartWidth<Extract<Head, TemplateLiteralPart>> extends infer Width ? [Width] extends [null] ? HasVariableCapture extends true ? false : TemplateLiteralIsFrameless<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, true> : [Width] extends [readonly []] ? TemplateLiteralIsFrameless<Extract<Tail, ReadonlyArray<TemplateLiteralPart>>, HasVariableCapture> : false : false : HasVariableCapture;
1723
+ type TemplateLiteralStringWidth<Value extends string, Width extends ReadonlyArray<unknown> = readonly []> = string extends Value ? null : Value extends "" ? Width : Value extends `${infer _CodePoint}${infer Tail}` ? TemplateLiteralStringWidth<Tail, readonly [...Width, unknown]> : null;
1450
1724
  /**
1451
1725
  * Branded {@link Type}.
1452
1726
  *
@@ -1800,7 +2074,7 @@ export interface CapitalizedError extends TypeError<"Capitalized"> {
1800
2074
  export declare const CapitalizedString: BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "Capitalized", CapitalizedError>;
1801
2075
  export type CapitalizedString = typeof CapitalizedString.Output;
1802
2076
  /**
1803
- * Adds a {@link Brand} requiring a string without surrounding whitespace.
2077
+ * String {@link Brand} without surrounding whitespace.
1804
2078
  *
1805
2079
  * @group String
1806
2080
  */
@@ -1829,7 +2103,7 @@ export type TrimmedString = typeof TrimmedString.Output;
1829
2103
  */
1830
2104
  export declare const trim: (value: string) => TrimmedString;
1831
2105
  /**
1832
- * Adds a {@link Brand} requiring a value to have at least `min` items.
2106
+ * Minimum-length {@link Brand} requiring a value to have at least `min` items.
1833
2107
  *
1834
2108
  * @group String
1835
2109
  * @group Collection
@@ -1857,7 +2131,7 @@ export interface MinLengthError<Min extends number = number> extends TypeError<`
1857
2131
  export declare const NonEmptyTrimmedString: BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "Trimmed", TrimmedError>, "MinLength1", MinLengthError<1>>;
1858
2132
  export type NonEmptyTrimmedString = typeof NonEmptyTrimmedString.Output;
1859
2133
  /**
1860
- * Adds a {@link Brand} requiring a value to have at most `max` items.
2134
+ * Maximum-length {@link Brand} requiring a value to have at most `max` items.
1861
2135
  *
1862
2136
  * @group String
1863
2137
  * @group Collection
@@ -1883,7 +2157,7 @@ export type NonEmptyTrimmedString100 = typeof NonEmptyTrimmedString100.Output;
1883
2157
  export declare const NonEmptyTrimmedString1000: BrandType<BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "Trimmed", TrimmedError>, "MinLength1", MinLengthError<1>>, "MaxLength1000", MaxLengthError<1000>>;
1884
2158
  export type NonEmptyTrimmedString1000 = typeof NonEmptyTrimmedString1000.Output;
1885
2159
  /**
1886
- * Adds a {@link Brand} requiring a value to have exactly `exact` items.
2160
+ * Exact-length {@link Brand} requiring a value to have exactly `exact` items.
1887
2161
  *
1888
2162
  * @group String
1889
2163
  * @group Collection
@@ -1895,7 +2169,7 @@ export interface LengthError<Exact extends number = number> extends TypeError<`L
1895
2169
  readonly exact: Exact;
1896
2170
  }
1897
2171
  /**
1898
- * Creates a string {@link Brand} that must match a regular expression.
2172
+ * String {@link Brand} constrained by a regular expression.
1899
2173
  *
1900
2174
  * ### Example
1901
2175
  *
@@ -2061,7 +2335,7 @@ export declare const createIdFromString: <B extends string = never>(value: strin
2061
2335
  */
2062
2336
  export declare const createIdAsUuidv7: <B extends string = never>(deps: RandomBytesDep & TimeDep, ..._validation: IdBrandValidation<B>) => CreatedId<B>;
2063
2337
  /**
2064
- * A table-specific {@link Id} Type.
2338
+ * Table-specific {@link Id} Type.
2065
2339
  *
2066
2340
  * @group String
2067
2341
  */
@@ -2118,7 +2392,7 @@ export interface Int64StringError extends TypeError<"Int64String"> {
2118
2392
  */
2119
2393
  export declare const Int64FromInt64String: TransformType<BrandType<BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "Trimmed", TrimmedError>, "MinLength1", MinLengthError<1>>, "Int64String", Int64StringError>, BrandType<Type<"BigInt", bigint, bigint, TypeOfError<"BigInt">, null, TypeOfError<"BigInt">, never, bigint, true>, "Int64", Int64Error>, "Int64FromInt64String", never, string & Brand<"Trimmed"> & Brand<"MinLength1"> & Brand<"Int64String">>;
2120
2394
  /**
2121
- * Adds a {@link Brand} requiring a number greater than or equal to zero.
2395
+ * Number {@link Brand} requiring a value greater than or equal to zero.
2122
2396
  *
2123
2397
  * @group Number
2124
2398
  */
@@ -2135,7 +2409,7 @@ export interface NonNegativeError extends TypeError<"NonNegative"> {
2135
2409
  export declare const NonNegativeNumber: BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNegative", NonNegativeError>;
2136
2410
  export type NonNegativeNumber = typeof NonNegativeNumber.Output;
2137
2411
  /**
2138
- * Adds a {@link Brand} requiring a number greater than zero.
2412
+ * Number {@link Brand} requiring a value greater than zero.
2139
2413
  *
2140
2414
  * @group Number
2141
2415
  */
@@ -2155,7 +2429,7 @@ export interface PositiveError extends TypeError<"Positive"> {
2155
2429
  export declare const PositiveNumber: BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNegative", NonNegativeError>, "Positive", PositiveError>;
2156
2430
  export type PositiveNumber = typeof PositiveNumber.Output;
2157
2431
  /**
2158
- * Adds a {@link Brand} requiring a number less than or equal to zero.
2432
+ * Number {@link Brand} requiring a value less than or equal to zero.
2159
2433
  *
2160
2434
  * @group Number
2161
2435
  */
@@ -2172,7 +2446,7 @@ export interface NonPositiveError extends TypeError<"NonPositive"> {
2172
2446
  export declare const NonPositiveNumber: BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonPositive", NonPositiveError>;
2173
2447
  export type NonPositiveNumber = typeof NonPositiveNumber.Output;
2174
2448
  /**
2175
- * Adds a {@link Brand} requiring a number less than zero.
2449
+ * Number {@link Brand} requiring a value less than zero.
2176
2450
  *
2177
2451
  * @group Number
2178
2452
  */
@@ -2192,7 +2466,7 @@ export interface NegativeError extends TypeError<"Negative"> {
2192
2466
  export declare const NegativeNumber: BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonPositive", NonPositiveError>, "Negative", NegativeError>;
2193
2467
  export type NegativeNumber = typeof NegativeNumber.Output;
2194
2468
  /**
2195
- * Adds a {@link Brand} requiring a number other than `NaN`.
2469
+ * Number {@link Brand} requiring a value other than `NaN`.
2196
2470
  *
2197
2471
  * @group Number
2198
2472
  */
@@ -2214,7 +2488,7 @@ export interface NonNaNError extends TypeError<"NonNaN"> {
2214
2488
  export declare const NonNaNNumber: BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNaN", NonNaNError>;
2215
2489
  export type NonNaNNumber = typeof NonNaNNumber.Output;
2216
2490
  /**
2217
- * Adds a {@link Brand} requiring a finite number.
2491
+ * Number {@link Brand} requiring a finite value.
2218
2492
  *
2219
2493
  * @group Number
2220
2494
  */
@@ -2285,12 +2559,6 @@ export type Int = typeof Int.Output;
2285
2559
  */
2286
2560
  export declare const NonNegativeInt: BrandType<BrandType<BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNaN", NonNaNError>, "Finite", FiniteError>, "Int", IntError>, "NonNegative", NonNegativeError>;
2287
2561
  export type NonNegativeInt = typeof NonNegativeInt.Output;
2288
- /**
2289
- * 0-100 as a literal, or any already-validated {@link NonNegativeInt}.
2290
- *
2291
- * @group Number
2292
- */
2293
- export type Int0To100OrNonNegativeInt = 0 | Int1To100 | NonNegativeInt;
2294
2562
  /**
2295
2563
  * Minimum {@link NonNegativeInt} value.
2296
2564
  *
@@ -2307,12 +2575,6 @@ export declare const zeroNonNegativeInt: number & Brand<"NonNaN"> & Brand<"Finit
2307
2575
  */
2308
2576
  export declare const PositiveInt: BrandType<BrandType<BrandType<BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNaN", NonNaNError>, "Finite", FiniteError>, "Int", IntError>, "NonNegative", NonNegativeError>, "Positive", PositiveError>;
2309
2577
  export type PositiveInt = typeof PositiveInt.Output;
2310
- /**
2311
- * 1-100 as a literal, or any already-validated {@link PositiveInt}.
2312
- *
2313
- * @group Number
2314
- */
2315
- export type Int1To100OrPositiveInt = Int1To100 | PositiveInt;
2316
2578
  /**
2317
2579
  * Minimum {@link PositiveInt} value.
2318
2580
  *
@@ -2343,7 +2605,7 @@ export type NonPositiveInt = typeof NonPositiveInt.Output;
2343
2605
  export declare const NegativeInt: BrandType<BrandType<BrandType<BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNaN", NonNaNError>, "Finite", FiniteError>, "Int", IntError>, "NonPositive", NonPositiveError>, "Negative", NegativeError>;
2344
2606
  export type NegativeInt = typeof NegativeInt.Output;
2345
2607
  /**
2346
- * Adds a {@link Brand} requiring a number greater than `min`.
2608
+ * Number {@link Brand} requiring a value greater than `min`.
2347
2609
  *
2348
2610
  * @group Number
2349
2611
  */
@@ -2354,7 +2616,7 @@ export interface GreaterThanError<Min extends number = number> extends TypeError
2354
2616
  readonly min: Min;
2355
2617
  }
2356
2618
  /**
2357
- * Adds a {@link Brand} requiring a number greater than or equal to `min`.
2619
+ * Number {@link Brand} requiring a value greater than or equal to `min`.
2358
2620
  *
2359
2621
  * @group Number
2360
2622
  */
@@ -2365,7 +2627,7 @@ export interface GreaterThanOrEqualToError<Min extends number = number> extends
2365
2627
  readonly min: Min;
2366
2628
  }
2367
2629
  /**
2368
- * Adds a {@link Brand} requiring a number less than `max`.
2630
+ * Number {@link Brand} requiring a value less than `max`.
2369
2631
  *
2370
2632
  * @group Number
2371
2633
  */
@@ -2383,7 +2645,7 @@ export interface LessThanError<Max extends number = number> extends TypeError<`L
2383
2645
  export declare const Age: BrandType<BrandType<BrandType<BrandType<BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNaN", NonNaNError>, "Finite", FiniteError>, "Int", IntError>, "NonNegative", NonNegativeError>, "LessThan200", LessThanError<200>>, "Age", never>;
2384
2646
  export type Age = typeof Age.Output;
2385
2647
  /**
2386
- * Adds a {@link Brand} requiring a number less than or equal to `max`.
2648
+ * Number {@link Brand} requiring a value less than or equal to `max`.
2387
2649
  *
2388
2650
  * @group Number
2389
2651
  */
@@ -2403,46 +2665,128 @@ export interface LessThanOrEqualToError<Max extends number = number> extends Typ
2403
2665
  export declare const Ratio: BrandType<BrandType<BrandType<BrandType<BrandType<Type<"Number", number, number, TypeOfError<"Number">, null, TypeOfError<"Number">, never, number, true>, "NonNaN", NonNaNError>, "Finite", FiniteError>, "NonNegative", NonNegativeError>, "LessThanOrEqualTo1", LessThanOrEqualToError<1>>, "Ratio", never>;
2404
2666
  export type Ratio = typeof Ratio.Output;
2405
2667
  /**
2406
- * Canonical string representation of a positive base-10 decimal value.
2668
+ * Canonical string representation of a signed base-10 decimal value.
2407
2669
  *
2408
2670
  * Use this Type when a decimal value must remain exact instead of being
2409
2671
  * converted to an IEEE-754 number. Equivalent values have one accepted
2410
- * representation, so leading zeroes, trailing fractional zeroes, signs, and
2411
- * exponent notation are rejected.
2672
+ * representation, so leading zeroes, trailing fractional zeroes, `-0`, plus
2673
+ * signs, and exponent notation are rejected.
2412
2674
  *
2413
2675
  * The decoded value remains a string. Arithmetic requires an explicit decimal
2414
2676
  * or fixed-point representation.
2415
2677
  *
2678
+ * TypeScript template literal types can describe a fixed number of digit
2679
+ * positions, but not the arbitrarily long integer and fractional parts accepted
2680
+ * here. `DecimalString` therefore uses a {@link Brand} so its TypeScript type
2681
+ * does not accept strings that have not been validated.
2682
+ *
2683
+ * Use these predefined Types or their corresponding factories to add sign
2684
+ * constraints to compatible decimal string Types:
2685
+ *
2686
+ * - {@link NonNegativeDecimalString} / {@link nonNegativeDecimalString}
2687
+ * - {@link PositiveDecimalString} / {@link positiveDecimalString}
2688
+ * - {@link NonPositiveDecimalString} / {@link nonPositiveDecimalString}
2689
+ * - {@link NegativeDecimalString} / {@link negativeDecimalString}
2690
+ *
2416
2691
  * ### Example
2417
2692
  *
2418
2693
  * ```ts
2419
- * import { PositiveDecimalString } from "@evolu/common";
2694
+ * import { DecimalString } from "@evolu/common";
2420
2695
  *
2421
- * expectOk(PositiveDecimalString.fromUnknown("0.3"), "0.3");
2422
- * expectOk(PositiveDecimalString.fromUnknown("25"), "25");
2423
- * expectOk(PositiveDecimalString.fromUnknown("10.01"), "10.01");
2696
+ * expectOk(DecimalString.fromUnknown("-10.25"), "-10.25");
2697
+ * expectOk(DecimalString.fromUnknown("0"), "0");
2698
+ * expectOk(DecimalString.fromUnknown("10.25"), "10.25");
2424
2699
  *
2425
- * expectErr(PositiveDecimalString.fromUnknown("0"), {
2426
- * type: "PositiveDecimalString",
2427
- * value: "0",
2428
- * });
2429
- * expectErr(PositiveDecimalString.fromUnknown("0.30"), {
2430
- * type: "PositiveDecimalString",
2431
- * value: "0.30",
2700
+ * expectErr(DecimalString.fromUnknown("10.250"), {
2701
+ * type: "DecimalString",
2702
+ * value: "10.250",
2432
2703
  * });
2433
2704
  * ```
2434
2705
  *
2435
2706
  * @group Number
2436
2707
  */
2437
- export declare const PositiveDecimalString: BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "PositiveDecimalString", PositiveDecimalStringError>;
2438
- export type PositiveDecimalString = typeof PositiveDecimalString.Output;
2708
+ export declare const DecimalString: BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "DecimalString", DecimalStringError>;
2709
+ export type DecimalString = typeof DecimalString.Output;
2710
+ /** @group Number */
2711
+ export interface DecimalStringError extends TypeError<"DecimalString"> {
2712
+ readonly value: string;
2713
+ }
2714
+ /**
2715
+ * {@link DecimalString} Brand requiring a value greater than or equal to zero.
2716
+ *
2717
+ * @group Number
2718
+ */
2719
+ export declare const nonNegativeDecimalString: BrandFactory<"NonNegativeDecimalString", DecimalString, NonNegativeDecimalStringError>;
2720
+ /** @group Number */
2721
+ export interface NonNegativeDecimalStringError extends TypeError<"NonNegativeDecimalString"> {
2722
+ readonly value: string;
2723
+ }
2724
+ /**
2725
+ * Non-negative {@link DecimalString}.
2726
+ *
2727
+ * @group Number
2728
+ */
2729
+ export declare const NonNegativeDecimalString: BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "DecimalString", DecimalStringError>, "NonNegativeDecimalString", NonNegativeDecimalStringError>;
2730
+ export type NonNegativeDecimalString = typeof NonNegativeDecimalString.Output;
2731
+ /**
2732
+ * {@link DecimalString} Brand requiring a value greater than zero.
2733
+ *
2734
+ * @group Number
2735
+ */
2736
+ export declare const positiveDecimalString: BrandFactory<"PositiveDecimalString", DecimalString, PositiveDecimalStringError>;
2439
2737
  /** @group Number */
2440
2738
  export interface PositiveDecimalStringError extends TypeError<"PositiveDecimalString"> {
2441
2739
  readonly value: string;
2442
2740
  }
2443
2741
  /**
2444
- * Adds a {@link Brand} requiring a number to be a multiple of an exact decimal
2445
- * `divisor`.
2742
+ * Positive {@link DecimalString}.
2743
+ *
2744
+ * Also satisfies {@link NonNegativeDecimalString}, so it can be used wherever a
2745
+ * non-negative decimal string is required.
2746
+ *
2747
+ * @group Number
2748
+ */
2749
+ export declare const PositiveDecimalString: BrandType<BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "DecimalString", DecimalStringError>, "NonNegativeDecimalString", NonNegativeDecimalStringError>, "PositiveDecimalString", PositiveDecimalStringError>;
2750
+ export type PositiveDecimalString = typeof PositiveDecimalString.Output;
2751
+ /**
2752
+ * {@link DecimalString} Brand requiring a value less than or equal to zero.
2753
+ *
2754
+ * @group Number
2755
+ */
2756
+ export declare const nonPositiveDecimalString: BrandFactory<"NonPositiveDecimalString", DecimalString, NonPositiveDecimalStringError>;
2757
+ /** @group Number */
2758
+ export interface NonPositiveDecimalStringError extends TypeError<"NonPositiveDecimalString"> {
2759
+ readonly value: string;
2760
+ }
2761
+ /**
2762
+ * Non-positive {@link DecimalString}.
2763
+ *
2764
+ * @group Number
2765
+ */
2766
+ export declare const NonPositiveDecimalString: BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "DecimalString", DecimalStringError>, "NonPositiveDecimalString", NonPositiveDecimalStringError>;
2767
+ export type NonPositiveDecimalString = typeof NonPositiveDecimalString.Output;
2768
+ /**
2769
+ * {@link DecimalString} Brand requiring a value less than zero.
2770
+ *
2771
+ * @group Number
2772
+ */
2773
+ export declare const negativeDecimalString: BrandFactory<"NegativeDecimalString", DecimalString, NegativeDecimalStringError>;
2774
+ /** @group Number */
2775
+ export interface NegativeDecimalStringError extends TypeError<"NegativeDecimalString"> {
2776
+ readonly value: string;
2777
+ }
2778
+ /**
2779
+ * Negative {@link DecimalString}.
2780
+ *
2781
+ * Also satisfies {@link NonPositiveDecimalString}, so it can be used wherever a
2782
+ * non-positive decimal string is required.
2783
+ *
2784
+ * @group Number
2785
+ */
2786
+ export declare const NegativeDecimalString: BrandType<BrandType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "DecimalString", DecimalStringError>, "NonPositiveDecimalString", NonPositiveDecimalStringError>, "NegativeDecimalString", NegativeDecimalStringError>;
2787
+ export type NegativeDecimalString = typeof NegativeDecimalString.Output;
2788
+ /**
2789
+ * Number {@link Brand} requiring an exact decimal multiple of `divisor`.
2446
2790
  *
2447
2791
  * The divisor must be one canonical positive decimal string literal because its
2448
2792
  * exact value is encoded in the resulting Brand name. The declaration is
@@ -2488,7 +2832,7 @@ type IsDecimalDigits<Value extends string> = Value extends "" ? true : Value ext
2488
2832
  type InvalidMultipleOfDivisor<Divisor extends string> = Divisor & Readonly<Record<MultipleOfDivisorError, never>>;
2489
2833
  type MultipleOfDivisorError = CompileTimeError<"MultipleOf", 'Divisor must be one canonical positive decimal string literal such as "0.1".'>;
2490
2834
  /**
2491
- * Adds a {@link Brand} requiring a number to be within an inclusive range.
2835
+ * Number {@link Brand} requiring a value within an inclusive range.
2492
2836
  *
2493
2837
  * @group Number
2494
2838
  */
@@ -2859,6 +3203,55 @@ interface TupleItemsErrorValue<Error extends TypeError, IncludeStructuralIssues
2859
3203
  readonly issues: NonEmptyReadonlyArray<(true extends IncludeStructuralIssues ? TupleStructuralIssue : never) | TupleElementIssue<Error>>;
2860
3204
  };
2861
3205
  }
3206
+ /**
3207
+ * Decimal digit from `"0"` to `"9"`.
3208
+ *
3209
+ * @group String
3210
+ */
3211
+ export declare const Digit: UnionType<readonly [LiteralType<"0">, LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>;
3212
+ export type Digit = typeof Digit.Output;
3213
+ /**
3214
+ * Decimal digit from `"1"` to `"9"`.
3215
+ *
3216
+ * @group String
3217
+ */
3218
+ export declare const Digit1To9: UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>;
3219
+ export type Digit1To9 = typeof Digit1To9.Output;
3220
+ /**
3221
+ * Decimal string from `"1"` to `"6"`.
3222
+ *
3223
+ * @group String
3224
+ */
3225
+ export declare const Digit1To6: UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">]>;
3226
+ export type Digit1To6 = typeof Digit1To6.Output;
3227
+ /**
3228
+ * Decimal string from `"1"` to `"23"`.
3229
+ *
3230
+ * @group String
3231
+ */
3232
+ export declare const Digit1To23: UnionType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>, TemplateLiteralType<readonly ["1", UnionType<readonly [LiteralType<"0">, LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>]>, TemplateLiteralType<readonly ["2", UnionType<readonly [LiteralType<"0">, LiteralType<"1">, LiteralType<"2">, LiteralType<"3">]>]>]>;
3233
+ export type Digit1To23 = typeof Digit1To23.Output;
3234
+ /**
3235
+ * Decimal string from `"1"` to `"51"`.
3236
+ *
3237
+ * @group String
3238
+ */
3239
+ export declare const Digit1To51: UnionType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>, TemplateLiteralType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">]>, UnionType<readonly [LiteralType<"0">, LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>]>, TemplateLiteralType<readonly ["5", UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>]>]>;
3240
+ export type Digit1To51 = typeof Digit1To51.Output;
3241
+ /**
3242
+ * Decimal string from `"1"` to `"99"`.
3243
+ *
3244
+ * @group String
3245
+ */
3246
+ export declare const Digit1To99: UnionType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>, TemplateLiteralType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>, UnionType<readonly [LiteralType<"0">, LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>]>]>;
3247
+ export type Digit1To99 = typeof Digit1To99.Output;
3248
+ /**
3249
+ * Decimal string from `"1"` to `"59"`.
3250
+ *
3251
+ * @group String
3252
+ */
3253
+ export declare const Digit1To59: UnionType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>, TemplateLiteralType<readonly [UnionType<readonly [LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">]>, UnionType<readonly [LiteralType<"0">, LiteralType<"1">, LiteralType<"2">, LiteralType<"3">, LiteralType<"4">, LiteralType<"5">, LiteralType<"6">, LiteralType<"7">, LiteralType<"8">, LiteralType<"9">]>]>]>;
3254
+ export type Digit1To59 = typeof Digit1To59.Output;
2862
3255
  type PlainObjectError = ObjectError<Readonly<Record<never, never>>, ObjectPropertyAccessError | ObjectExcessPropertyError>;
2863
3256
  /**
2864
3257
  * A {@link Type} for readonly plain objects with unknown property values.
@@ -3470,7 +3863,7 @@ type ObjectUnknownPropertyErrors<Error extends TypeError, RestError extends Type
3470
3863
  type ObjectRestFromUnknownError<Rest extends ObjectRecordTypeNode | undefined> = Rest extends ObjectRecordTypeNode ? ObjectPropertyAccessError | RecordEntriesErrorValue<TypeOfError<"String">, InferErrors<Rest["value"]>, never> : ObjectExcessPropertyError;
3471
3864
  type ObjectRestFromParentError<Rest extends ObjectRecordTypeNode | undefined> = Rest extends ObjectRecordTypeNode ? RecordEntriesError<never, TypeFromError<Rest["value"]>, never> : never;
3472
3865
  /**
3473
- * Creates an {@link object} Type with every property optional.
3866
+ * Object {@link Type} with every property optional.
3474
3867
  *
3475
3868
  * No property is required, but every present property must still satisfy its
3476
3869
  * Type.
@@ -3495,7 +3888,8 @@ export type PartialObjectProps<Props extends ObjectProps> = {
3495
3888
  readonly [Key in keyof Props]: Props[Key] extends OptionalProperty<TypeNode> ? Props[Key] : Props[Key] extends TypeNode ? OptionalProperty<Props[Key]> : never;
3496
3889
  };
3497
3890
  /**
3498
- * Makes every property whose Union Type includes {@link Null} optional.
3891
+ * Object {@link Type} making every property whose Union Type includes
3892
+ * {@link Null} optional.
3499
3893
  *
3500
3894
  * The property retains its original Union Type, so consumers may omit it, set
3501
3895
  * it to `null`, or provide any other member of that Union. Properties without
@@ -3526,7 +3920,7 @@ export type NullableToOptionalProps<Props extends ObjectProps> = {
3526
3920
  readonly [Key in keyof Props]: Props[Key] extends OptionalProperty<TypeNode> ? Props[Key] : Props[Key] extends UnionType<infer Members> ? typeof Null extends Members[number] ? OptionalProperty<Props[Key]> : Props[Key] : Props[Key];
3527
3921
  };
3528
3922
  /**
3529
- * Creates an {@link object} Type without the selected declared properties.
3923
+ * Object {@link Type} without the selected declared properties.
3530
3924
  *
3531
3925
  * @group Objects
3532
3926
  */
@@ -3537,7 +3931,7 @@ type ValidateOmitKeys<Keys extends ReadonlyArray<PropertyKey>> = number extends
3537
3931
  type OmitKeysTupleError = CompileTimeError<"Type", "Omitted keys must use one concrete finite tuple.">;
3538
3932
  type OmitKeyConcreteTypeError = CompileTimeError<"Type", "Each omitted key must be one concrete property key.">;
3539
3933
  /**
3540
- * Creates a {@link Type} for {@link Result} values.
3934
+ * {@link Result} {@link Type} for typed success and error values.
3541
3935
  *
3542
3936
  * Use this to validate Results crossing a storage, worker, API, or other
3543
3937
  * serialization boundary. The operation returns an outer validation Result. Its
@@ -3737,7 +4131,7 @@ type ConcreteTypedTagError = CompileTimeError<"Type", "Tag must be one concrete
3737
4131
  type TypedValidationError<Props extends ObjectProps> = "type" extends keyof Props ? TypedTypePropertyError : ObjectValidationError<Props>;
3738
4132
  type TypedTypePropertyError = CompileTimeError<"Type", 'Additional properties must not declare the reserved "type" property.'>;
3739
4133
  /**
3740
- * Creates a {@link Type} for a producer's value, error, or done {@link Result}.
4134
+ * Producer-result {@link Type} for value, error, or done outcomes.
3741
4135
  *
3742
4136
  * The three outcomes are `Ok<Value>`, `Err<Error>`, and `Err<Typed<"Done"> & {
3743
4137
  * done: Done }>`. This keeps normal completion distinct from failure while
@@ -4234,7 +4628,7 @@ export declare const jsonValueToJson: (value: JsonValue) => Json;
4234
4628
  */
4235
4629
  export declare const JsonValueFromJson: TransformType<BrandType<Type<"String", string, string, TypeOfError<"String">, null, TypeOfError<"String">, never, string, true>, "Json", JsonError>, JsonValueType, "JsonValueFromJson", never, string & Brand<"Json">>;
4236
4630
  /**
4237
- * Creates a branded {@link Json} Type and total conversions for another Type.
4631
+ * Branded {@link Json} Type and total conversions for another Type.
4238
4632
  *
4239
4633
  * Use this factory when a domain value must be stored as JSON text while its
4240
4634
  * exact Type remains visible to TypeScript, such as a JSON column in an Evolu