ts-fortress 8.5.2 → 9.0.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.
Files changed (35) hide show
  1. package/README.md +8 -5
  2. package/dist/predefined/brand/string/email.d.mts +2 -2
  3. package/dist/predefined/brand/string/email.d.mts.map +1 -1
  4. package/dist/predefined/brand/string/email.mjs +4 -3
  5. package/dist/predefined/brand/string/email.mjs.map +1 -1
  6. package/dist/predefined/brand/string/iso-8601.d.mts +2 -2
  7. package/dist/predefined/brand/string/iso-8601.d.mts.map +1 -1
  8. package/dist/predefined/brand/string/iso-8601.mjs +2 -3
  9. package/dist/predefined/brand/string/iso-8601.mjs.map +1 -1
  10. package/dist/predefined/brand/string/json-string.d.mts +2 -2
  11. package/dist/predefined/brand/string/json-string.d.mts.map +1 -1
  12. package/dist/predefined/brand/string/json-string.mjs +4 -3
  13. package/dist/predefined/brand/string/json-string.mjs.map +1 -1
  14. package/dist/predefined/brand/string/uri.d.mts +2 -2
  15. package/dist/predefined/brand/string/uri.d.mts.map +1 -1
  16. package/dist/predefined/brand/string/uri.mjs +2 -3
  17. package/dist/predefined/brand/string/uri.mjs.map +1 -1
  18. package/dist/predefined/brand/string/uuid.d.mts +5 -5
  19. package/dist/predefined/brand/string/uuid.d.mts.map +1 -1
  20. package/dist/predefined/brand/string/uuid.mjs +2 -2
  21. package/dist/predefined/brand/string/uuid.mjs.map +1 -1
  22. package/dist/primitives/string.d.mts +37 -22
  23. package/dist/primitives/string.d.mts.map +1 -1
  24. package/dist/primitives/string.mjs +24 -2
  25. package/dist/primitives/string.mjs.map +1 -1
  26. package/package.json +3 -3
  27. package/src/predefined/brand/string/email.mts +9 -7
  28. package/src/predefined/brand/string/iso-8601.mts +11 -8
  29. package/src/predefined/brand/string/json-string.mts +9 -8
  30. package/src/predefined/brand/string/non-empty-string.test.mts +4 -3
  31. package/src/predefined/brand/string/uri.mts +7 -7
  32. package/src/predefined/brand/string/uuid.mts +14 -10
  33. package/src/primitives/string.mts +125 -41
  34. package/src/primitives/string.test.mts +95 -11
  35. package/src/record/key-value-record.test.mts +1 -2
package/README.md CHANGED
@@ -277,17 +277,20 @@ Slug.is('feature-beta'); // true
277
277
 
278
278
  Slug.is('Feature-Flag'); // false (fails regex)
279
279
 
280
- type SlugType = t.TypeOf<typeof Slug>; // inferred as `feature${string}`
280
+ type SlugType = t.TypeOf<typeof Slug>;
281
+ // inferred as a `feature${string}` template literal branded with
282
+ // `NonEmptyString`, `MinLengthString<6>` and `MaxLengthString<32>`
281
283
  ```
282
284
 
283
285
  String constraints:
284
286
 
285
- - `startsWith`, `endsWith`, `includes`
286
- - `lowercase`, `uppercase`, `nonempty`
287
- - `minLength`, `maxLength`
287
+ - `startsWith`, `endsWith`, `includes` — narrow the result to the corresponding template literal type
288
+ - `lowercase`, `uppercase`
289
+ - `nonempty` — brands the result as `NonEmptyString` (from [ts-type-forge](https://github.com/noshiro-pf/ts-type-forge))
290
+ - `minLength`, `maxLength` — brand the result as `MinLengthString<N>` / `MaxLengthString<N>` (from ts-type-forge), which preserve the natural subtyping between length bounds
288
291
  - `regex`
289
292
 
290
- A negative `minLength` is ignored so you can enable or disable the bound dynamically without branching.
293
+ `minLength` / `maxLength` accept plain `number`s, which must be positive integers (`>= 1`) — passing a non-integer or a value less than `1` throws a `TypeError` when the type is constructed. Number literals in the range `1..39` are encoded in the result brand (`MinLengthString<N>` / `MaxLengthString<N>`); larger literals and dynamically computed `number`s are still enforced at runtime, but the result type falls back to plain `string` to keep the type-level computation cheap.
291
294
 
292
295
  ### Number constraints
293
296
 
@@ -1,6 +1,6 @@
1
- import { type Brand } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
2
2
  import { type Type } from '../../../type.mjs';
3
- export type Email = Brand<string, 'Email' | 'NonEmptyString'>;
3
+ export type Email = Brand<NonEmptyString, 'Email'>;
4
4
  /**
5
5
  * @link https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
6
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"email.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/email.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAG9C,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAAC,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,KAAK,GAChB,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,KACA,IAAI,CAAC,KAAK,CAOT,CAAC"}
1
+ {"version":3,"file":"email.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/email.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,KAAK,GAChB,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,KACA,IAAI,CAAC,KAAK,CAQT,CAAC"}
@@ -8,10 +8,11 @@ import { string } from '../../../primitives/string.mjs';
8
8
  * @link https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
9
9
  */
10
10
  const email = (options) => brand({
11
- baseType: string(options?.defaultValue ?? defaultEmail),
11
+ baseType: string(options?.defaultValue ?? defaultEmail, {
12
+ nonempty: true,
13
+ }),
12
14
  is: (s) => regexpEmailAddress.test(s),
13
- defaultValue: options?.defaultValue ?? defaultEmail,
14
- brandKeys: ['Email', 'NonEmptyString'],
15
+ brandKeys: ['Email'],
15
16
  typeName: 'Email',
16
17
  });
17
18
  const defaultEmail = 'ts-f.o.r.t.r.e.s.s@gmail.com';
@@ -1 +1 @@
1
- {"version":3,"file":"email.mjs","sources":["../../../../src/predefined/brand/string/email.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAQA;;AAEG;AACI,MAAM,KAAK,GAAG,CACnB,OAIC,KAED,KAAK,CAAC;IACJ,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,YAAY,CAAC;IACvD,EAAE,EAAE,CAAC,CAAC,KAAiB,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,IAAA,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,YAAY;AACnD,IAAA,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC;AACtC,IAAA,QAAQ,EAAE,OAAO;AAClB,CAAA;AAEH,MAAM,YAAY,GAAG,8BAA8B;AAEnD,MAAM,kBAAkB;AACtB;AACA,uIAAuI;;;;"}
1
+ {"version":3,"file":"email.mjs","sources":["../../../../src/predefined/brand/string/email.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AASA;;AAEG;AACI,MAAM,KAAK,GAAG,CACnB,OAIC,KAED,KAAK,CAAqC;IACxC,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,YAAY,EAAE;AACtD,QAAA,QAAQ,EAAE,IAAI;KACf,CAAC;IACF,EAAE,EAAE,CAAC,CAAC,KAAiB,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,SAAS,EAAE,CAAC,OAAO,CAAC;AACpB,IAAA,QAAQ,EAAE,OAAO;AAClB,CAAA;AAEH,MAAM,YAAY,GAAG,8BAA8B;AAEnD,MAAM,kBAAkB;AACtB;AACA,uIAAuI;;;;"}
@@ -1,6 +1,6 @@
1
- import { type Brand } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
2
2
  import { type Type, type TypeOf } from '../../../type.mjs';
3
- export type Iso8601 = Brand<string, 'Iso8601' | 'NonEmptyString'>;
3
+ export type Iso8601 = Brand<NonEmptyString, 'Iso8601'>;
4
4
  /**
5
5
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
6
6
  * @link https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
@@ -1 +1 @@
1
- {"version":3,"file":"iso-8601.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/iso-8601.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAmB,MAAM,eAAe,CAAC;AAI5D,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3D,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,sBAAsB,KAAG,IAAI,CAAC,OAAO,CAYtE,CAAC;AAEF,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB1B,CAAC;AAEH,KAAK,sBAAsB,GAAG,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
1
+ {"version":3,"file":"iso-8601.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/iso-8601.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,cAAc,EAEpB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3D,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,sBAAsB,KAAG,IAAI,CAAC,OAAO,CAWtE,CAAC;AAEF,QAAA,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB1B,CAAC;AAEH,KAAK,sBAAsB,GAAG,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -15,10 +15,9 @@ const iso8601 = (options) => {
15
15
  const filledOptions = ISO8601ValidatorOption.fill(options);
16
16
  const is = isISO8601(filledOptions);
17
17
  return brand({
18
- baseType: string(filledOptions.defaultValue),
18
+ baseType: string(filledOptions.defaultValue, { nonempty: true }),
19
19
  is,
20
- defaultValue: filledOptions.defaultValue,
21
- brandKeys: ['Iso8601', 'NonEmptyString'],
20
+ brandKeys: ['Iso8601'],
22
21
  typeName: 'Iso8601',
23
22
  });
24
23
  };
@@ -1 +1 @@
1
- {"version":3,"file":"iso-8601.mjs","sources":["../../../../src/predefined/brand/string/iso-8601.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"iso-8601.mjs","sources":["../../../../src/predefined/brand/string/iso-8601.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { type Brand } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
2
2
  import { type Type } from '../../../type.mjs';
3
- export type JsonString = Brand<string, 'JsonString' | 'NonEmptyString'>;
3
+ export type JsonString = Brand<NonEmptyString, 'JsonString'>;
4
4
  /**
5
5
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
6
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"json-string.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/json-string.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAAC,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,KACA,IAAI,CAAC,UAAU,CAOd,CAAC"}
1
+ {"version":3,"file":"json-string.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/json-string.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,KACA,IAAI,CAAC,UAAU,CAQd,CAAC"}
@@ -8,10 +8,11 @@ import { string } from '../../../primitives/string.mjs';
8
8
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
9
9
  */
10
10
  const jsonString = (options) => brand({
11
- baseType: string(options?.defaultValue ?? defaultJsonString),
11
+ baseType: string(options?.defaultValue ?? defaultJsonString, {
12
+ nonempty: true,
13
+ }),
12
14
  is: isJsonString,
13
- defaultValue: options?.defaultValue ?? defaultJsonString,
14
- brandKeys: ['JsonString', 'NonEmptyString'],
15
+ brandKeys: ['JsonString'],
15
16
  typeName: 'JsonString',
16
17
  });
17
18
  const defaultJsonString = '{}';
@@ -1 +1 @@
1
- {"version":3,"file":"json-string.mjs","sources":["../../../../src/predefined/brand/string/json-string.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAUA;;AAEG;AACI,MAAM,UAAU,GAAG,CACxB,OAIC,KAED,KAAK,CAAC;IACJ,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,iBAAiB,CAAC;AAC5D,IAAA,EAAE,EAAE,YAAY;AAChB,IAAA,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,iBAAiB;AACxD,IAAA,SAAS,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC;AAC3C,IAAA,QAAQ,EAAE,YAAY;AACvB,CAAA;AAEH,MAAM,iBAAiB,GAAG,IAAI;AAE9B,MAAM,YAAY,GAAG,CAAC,GAAW,KAAuB;AACtD,IAAA,IAAI;QACF,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,KAAK;IACd;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"json-string.mjs","sources":["../../../../src/predefined/brand/string/json-string.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAUA;;AAEG;AACI,MAAM,UAAU,GAAG,CACxB,OAIC,KAED,KAAK,CAA0C;IAC7C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,iBAAiB,EAAE;AAC3D,QAAA,QAAQ,EAAE,IAAI;KACf,CAAC;AACF,IAAA,EAAE,EAAE,YAAY;IAChB,SAAS,EAAE,CAAC,YAAY,CAAC;AACzB,IAAA,QAAQ,EAAE,YAAY;AACvB,CAAA;AAEH,MAAM,iBAAiB,GAAG,IAAI;AAE9B,MAAM,YAAY,GAAG,CAAC,GAAW,KAAuB;AACtD,IAAA,IAAI;QACF,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,KAAK;IACd;AACF,CAAC;;;;"}
@@ -1,6 +1,6 @@
1
- import { type Brand } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
2
2
  import { type Type } from '../../../type.mjs';
3
- export type Uri = Brand<string, 'Uri' | 'NonEmptyString'>;
3
+ export type Uri = Brand<NonEmptyString, 'Uri'>;
4
4
  /**
5
5
  * @link https://url.spec.whatwg.org/
6
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"uri.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/uri.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAG9C,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,GAAG,GACd,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,KACA,IAAI,CAAC,GAAG,CAOP,CAAC"}
1
+ {"version":3,"file":"uri.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/uri.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,GAAG,GACd,UAAU,OAAO,CACf,QAAQ,CAAC;IACP,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,KACA,IAAI,CAAC,GAAG,CAMP,CAAC"}
@@ -8,10 +8,9 @@ import { string } from '../../../primitives/string.mjs';
8
8
  * @link https://url.spec.whatwg.org/
9
9
  */
10
10
  const uri = (options) => brand({
11
- baseType: string(options?.defaultValue ?? defaultUri),
11
+ baseType: string(options?.defaultValue ?? defaultUri, { nonempty: true }),
12
12
  is: isUri,
13
- defaultValue: options?.defaultValue ?? defaultUri,
14
- brandKeys: ['Uri', 'NonEmptyString'],
13
+ brandKeys: ['Uri'],
15
14
  typeName: 'Uri',
16
15
  });
17
16
  const defaultUri = 'https://example.com';
@@ -1 +1 @@
1
- {"version":3,"file":"uri.mjs","sources":["../../../../src/predefined/brand/string/uri.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAQA;;AAEG;AACI,MAAM,GAAG,GAAG,CACjB,OAIC,KAED,KAAK,CAAC;IACJ,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,UAAU,CAAC;AACrD,IAAA,EAAE,EAAE,KAAK;AACT,IAAA,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,UAAU;AACjD,IAAA,SAAS,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC;AACpC,IAAA,QAAQ,EAAE,KAAK;AAChB,CAAA;AAEH,MAAM,UAAU,GAAG,qBAAqB;AAExC;AACA;AACA,MAAM,KAAK,GAAG,CAAC,CAAS,KAAe,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;;;;"}
1
+ {"version":3,"file":"uri.mjs","sources":["../../../../src/predefined/brand/string/uri.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AASA;;AAEG;AACI,MAAM,GAAG,GAAG,CACjB,OAIC,KAED,KAAK,CAAmC;AACtC,IAAA,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACzE,IAAA,EAAE,EAAE,KAAK;IACT,SAAS,EAAE,CAAC,KAAK,CAAC;AAClB,IAAA,QAAQ,EAAE,KAAK;AAChB,CAAA;AAEH,MAAM,UAAU,GAAG,qBAAqB;AAExC;AACA;AACA,MAAM,KAAK,GAAG,CAAC,CAAS,KAAe,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;;;;"}
@@ -1,11 +1,11 @@
1
- import { type Brand, type TypeEq, type UintRangeInclusive } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString, type TypeEq, type UintRangeInclusive } from 'ts-type-forge';
2
2
  import { type Type } from '../../../type.mjs';
3
3
  export type UuidVersion = UintRangeInclusive<1, 8>;
4
4
  export type UuidBaseString<V extends UuidVersion = UuidVersion> = `${string}-${string}-${V}${string}-${string}-${string}` | '00000000-0000-0000-0000-000000000000' | 'ffffffff-ffff-ffff-ffff-ffffffffffff';
5
- export type Uuid = Brand<UuidBaseString, 'Uuid' | 'NonEmptyString'>;
6
- export type Uuid4 = Brand<UuidBaseString<4>, 'Uuid' | 'NonEmptyString'>;
7
- export type Uuid6 = Brand<UuidBaseString<6>, 'Uuid' | 'NonEmptyString'>;
8
- export type Uuid7 = Brand<UuidBaseString<7>, 'Uuid' | 'NonEmptyString'>;
5
+ export type Uuid = Brand<UuidBaseString & NonEmptyString, 'Uuid'>;
6
+ export type Uuid4 = Brand<UuidBaseString<4> & NonEmptyString, 'Uuid'>;
7
+ export type Uuid6 = Brand<UuidBaseString<6> & NonEmptyString, 'Uuid'>;
8
+ export type Uuid7 = Brand<UuidBaseString<7> & NonEmptyString, 'Uuid'>;
9
9
  /**
10
10
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
11
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"uuid.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/uuid.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EAEV,KAAK,MAAM,EACX,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEnD,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAC1D,GAAG,MAAM,IAAI,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,GACvD,sCAAsC,GACtC,sCAAsC,CAAC;AAI3C,MAAM,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;AAEpE,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;AAExE,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;AAExE,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,WAAW,GAAG,2BAA2B,EACtE,UAAU,mBAAmB,CAAC,CAAC,CAAC,KAC/B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAyBhB,CAAC;AAEF,KAAK,2BAA2B,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAEnE,KAAK,MAAM,CAAC,CAAC,SAAS,WAAW,GAAG,2BAA2B,IAC7D,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACrB,KAAK,GACL,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACvB,KAAK,GACL,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACvB,KAAK,GACL,IAAI,CAAC;AAEf,eAAO,MAAM,MAAM,GAAI,eAAe,MAAM,KAAG,IAAI,CAAC,KAAK,CAIrD,CAAC;AAEL,eAAO,MAAM,MAAM,GAAI,eAAe,MAAM,KAAG,IAAI,CAAC,KAAK,CAIrD,CAAC;AAEL,eAAO,MAAM,MAAM,GAAI,eAAe,MAAM,KAAG,IAAI,CAAC,KAAK,CAIrD,CAAC;AAEL,KAAK,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,2BAA2B,IAC1E,OAAO,CACL,QAAQ,CAAC;IACP;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC;IAEX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,CAAC"}
1
+ {"version":3,"file":"uuid.d.mts","sourceRoot":"","sources":["../../../../src/predefined/brand/string/uuid.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,cAAc,EAEnB,KAAK,MAAM,EACX,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEnD,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAC1D,GAAG,MAAM,IAAI,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,GACvD,sCAAsC,GACtC,sCAAsC,CAAC;AAK3C,MAAM,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,GAAG,cAAc,EAAE,MAAM,CAAC,CAAC;AAElE,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,MAAM,CAAC,CAAC;AAEtE,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,MAAM,CAAC,CAAC;AAEtE,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,MAAM,CAAC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,WAAW,GAAG,2BAA2B,EACtE,UAAU,mBAAmB,CAAC,CAAC,CAAC,KAC/B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CA2BhB,CAAC;AAEF,KAAK,2BAA2B,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAEnE,KAAK,MAAM,CAAC,CAAC,SAAS,WAAW,GAAG,2BAA2B,IAC7D,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACrB,KAAK,GACL,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACvB,KAAK,GACL,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACvB,KAAK,GACL,IAAI,CAAC;AAEf,eAAO,MAAM,MAAM,GAAI,eAAe,MAAM,KAAG,IAAI,CAAC,KAAK,CAIrD,CAAC;AAEL,eAAO,MAAM,MAAM,GAAI,eAAe,MAAM,KAAG,IAAI,CAAC,KAAK,CAIrD,CAAC;AAEL,eAAO,MAAM,MAAM,GAAI,eAAe,MAAM,KAAG,IAAI,CAAC,KAAK,CAIrD,CAAC;AAEL,KAAK,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,2BAA2B,IAC1E,OAAO,CACL,QAAQ,CAAC;IACP;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC;IAEX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CACH,CAAC"}
@@ -13,11 +13,11 @@ const uuid = (options) => {
13
13
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
14
14
  return brand({
15
15
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
16
- baseType: string(defaultValue),
16
+ baseType: string(defaultValue, { nonempty: true }),
17
17
  is: (s) => uuidDef[version](s),
18
18
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
19
19
  defaultValue: defaultValue,
20
- brandKeys: ['Uuid', 'NonEmptyString'],
20
+ brandKeys: ['Uuid'],
21
21
  typeName: options?.typeName ??
22
22
  (version === 4
23
23
  ? 'UuidV4'
@@ -1 +1 @@
1
- {"version":3,"file":"uuid.mjs","sources":["../../../../src/predefined/brand/string/uuid.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AA2BA;;AAEG;AACI,MAAM,IAAI,GAAG,CAClB,OAAgC,KACb;AAGnB,IAAA,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,OAAO;AAErD,IAAA,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,KAAK;;AAGzC,IAAA,OAAO,KAAK,CAAsD;;AAEhE,QAAA,QAAQ,EAAE,MAAM,CAAC,YAAY,CAAyB;AACtD,QAAA,EAAE,EAAE,CAAC,CAAC,KAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;;AAEtC,QAAA,YAAY,EAAE,YAA8B;AAC5C,QAAA,SAAS,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC;QACrC,QAAQ,EACN,OAAO,EAAE,QAAQ;aAChB,OAAO,KAAK;AACX,kBAAE;kBACA,OAAO,KAAK;AACZ,sBAAE;sBACA,OAAO,KAAK;AACZ,0BAAE;0BACA,MAAM,CAAC;AAClB,KAAA,CAAsC;AACzC;AAaO,MAAM,MAAM,GAAG,CAAC,YAAqB,KAC1C,IAAI,CAAC;IACH,YAAY,EAAE,YAAY,IAAI,sCAAsC;AACpE,IAAA,OAAO,EAAE,CAAC;AACX,CAAA;AAEI,MAAM,MAAM,GAAG,CAAC,YAAqB,KAC1C,IAAI,CAAC;IACH,YAAY,EAAE,YAAY,IAAI,sCAAsC;AACpE,IAAA,OAAO,EAAE,CAAC;AACX,CAAA;AAEI,MAAM,MAAM,GAAG,CAAC,YAAqB,KAC1C,IAAI,CAAC;IACH,YAAY,EAAE,YAAY,IAAI,sCAAsC;AACpE,IAAA,OAAO,EAAE,CAAC;AACX,CAAA;AAeH,MAAM,OAAO,GAAG,sCAA+D;AAE/E,MAAM,OAAO,GAAG,sCAA+D;AAE/E,MAAM,QAAQ,GAAG;AACf,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,CAAC,EAAE,mEAAmE;AACtE,IAAA,KAAK,EAAE,4DAA4D;AACnE,IAAA,KAAK,EACH,4EAA4E;CACtE;AAEV,MAAM,OAAO,GAGT;AACF,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7B,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,OAAO;IACzB,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,OAAO;AACzB,IAAA,KAAK,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;CAC7D;;;;"}
1
+ {"version":3,"file":"uuid.mjs","sources":["../../../../src/predefined/brand/string/uuid.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { type NonEmptyString } from 'ts-type-forge';
1
+ import { type MaxLengthString, type MinLengthString, type NonEmptyString, type SmallInt } from 'ts-type-forge';
2
2
  import { type Type } from '../type.mjs';
3
3
  export declare function string(defaultValue?: string): Type<string>;
4
- export declare function string<S extends string, const C extends Constraints>(defaultValue: S & DefaultValueType<S, C>, constraints: C): Type<ConstraintsResultType<C>>;
5
- type Constraints = Partial<Readonly<{
4
+ export declare function string<S extends string, const C extends RawConstraints>(defaultValue: S & DefaultValueType<S, C>, constraints: C): Type<ConstraintsResultType<C>>;
5
+ type RawConstraints = Partial<Readonly<{
6
6
  nonempty: true;
7
7
  minLength: number;
8
8
  maxLength: number;
@@ -16,49 +16,64 @@ type Constraints = Partial<Readonly<{
16
16
  /**
17
17
  * The set of constraints accepted by {@link string}.
18
18
  */
19
- export type StringTypeConstraints = Constraints;
19
+ export type StringTypeConstraints = RawConstraints;
20
20
  /**
21
21
  * The result type produced by {@link string} for a given set of constraints
22
- * `C` (e.g. `nonempty` yields {@link NonEmptyString}, `startsWith` narrows to a
23
- * template literal type, etc.).
22
+ * `C` (e.g. `nonempty` yields {@link NonEmptyString}, `minLength` /
23
+ * `maxLength` yield {@link MinLengthString} / {@link MaxLengthString},
24
+ * `startsWith` narrows to a template literal type, etc.).
24
25
  */
25
26
  export type StringConstraintsResultType<C extends StringTypeConstraints> = ConstraintsResultType<C>;
26
- type DefaultValueType<S extends string, C extends Constraints> = DefaultValueWhenNonemptyIsOn<S, C> & DefaultValueWhenMinLengthIsOn<S, C> & DefaultValueWhenMaxLengthIsOn<S, C> & DefaultValueWhenStartsWithIsOn<C> & DefaultValueWhenEndsWithIsOn<C> & DefaultValueWhenIncludesIsOn<C> & DefaultValueWhenUppercaseIsOn<S, C> & DefaultValueWhenLowercaseIsOn<S, C>;
27
- type ConstraintsResultType<C extends Constraints> = ConstraintsResultTypeWhenNonemptyIsOn<C> & DefaultValueWhenStartsWithIsOn<C> & DefaultValueWhenEndsWithIsOn<C> & DefaultValueWhenIncludesIsOn<C>;
28
- type DefaultValueWhenStartsWithIsOn<C extends Constraints> = C extends Readonly<{
27
+ type DefaultValueType<S extends string, C extends RawConstraints> = DefaultValueWhenNonemptyIsOn<S, C> & DefaultValueWhenMinLengthIsOn<S, C> & DefaultValueWhenMaxLengthIsOn<S, C> & DefaultValueWhenStartsWithIsOn<C> & DefaultValueWhenEndsWithIsOn<C> & DefaultValueWhenIncludesIsOn<C> & DefaultValueWhenUppercaseIsOn<S, C> & DefaultValueWhenLowercaseIsOn<S, C>;
28
+ type ConstraintsResultType<C extends RawConstraints> = ConstraintsResultTypeWhenNonemptyIsOn<C> & ConstraintsResultTypeWhenMinLengthIsOn<C> & ConstraintsResultTypeWhenMaxLengthIsOn<C> & DefaultValueWhenStartsWithIsOn<C> & DefaultValueWhenEndsWithIsOn<C> & DefaultValueWhenIncludesIsOn<C>;
29
+ type DefaultValueWhenStartsWithIsOn<C extends RawConstraints> = C extends Readonly<{
29
30
  startsWith: infer S extends string;
30
31
  }> ? `${S}${string}` : string;
31
- type DefaultValueWhenEndsWithIsOn<C extends Constraints> = C extends Readonly<{
32
+ type DefaultValueWhenEndsWithIsOn<C extends RawConstraints> = C extends Readonly<{
32
33
  endsWith: infer E extends string;
33
34
  }> ? `${string}${E}` : string;
34
- type DefaultValueWhenIncludesIsOn<C extends Constraints> = C extends Readonly<{
35
+ type DefaultValueWhenIncludesIsOn<C extends RawConstraints> = C extends Readonly<{
35
36
  includes: infer M extends string;
36
37
  }> ? `${string}${M}${string}` : string;
37
- type DefaultValueWhenUppercaseIsOn<S extends string, C extends Constraints> = C extends Readonly<{
38
+ type DefaultValueWhenUppercaseIsOn<S extends string, C extends RawConstraints> = C extends Readonly<{
38
39
  uppercase: true;
39
40
  }> ? CastUppercase<S> : string;
40
- type DefaultValueWhenLowercaseIsOn<S extends string, C extends Constraints> = C extends Readonly<{
41
+ type DefaultValueWhenLowercaseIsOn<S extends string, C extends RawConstraints> = C extends Readonly<{
41
42
  lowercase: true;
42
43
  }> ? CastLowercase<S> : string;
43
44
  type CastLowercase<S extends string> = S extends Lowercase<S> ? S : never;
44
45
  type CastUppercase<S extends string> = S extends Uppercase<S> ? S : never;
45
- type DefaultValueWhenNonemptyIsOn<S extends string, C extends Constraints> = C extends Readonly<{
46
+ type DefaultValueWhenNonemptyIsOn<S extends string, C extends RawConstraints> = C extends Readonly<{
46
47
  nonempty: true;
47
48
  }> ? RejectEmptyString<S> : string;
48
49
  type RejectEmptyString<S extends string> = S extends '' ? never : S;
49
- type ConstraintsResultTypeWhenNonemptyIsOn<C extends Constraints> = C extends Readonly<{
50
+ type ConstraintsResultTypeWhenNonemptyIsOn<C extends RawConstraints> = C extends Readonly<{
50
51
  nonempty: true;
51
52
  }> ? NonEmptyString : string;
52
- type DefaultValueWhenMinLengthIsOn<S extends string, C extends Constraints> = C extends Readonly<{
53
+ /**
54
+ * The length-bound literals supported at the type level: `SmallInt<'>0'>`
55
+ * (i.e. `1 | 2 | ... | 39`). Only bounds within this range are encoded in
56
+ * the result brand; larger literals and non-literal `number`s collapse to
57
+ * plain `string` to keep the type-level computation cheap (the runtime
58
+ * constraint applies regardless). Non-integer bounds and bounds less than 1
59
+ * throw a `TypeError` when the type is constructed.
60
+ */
61
+ type SupportedLengthLiteral = SmallInt<'>0'>;
62
+ type ConstraintsResultTypeWhenMinLengthIsOn<C extends RawConstraints> = C extends Readonly<{
63
+ minLength: infer M extends number;
64
+ }> ? [M] extends [SupportedLengthLiteral] ? MinLengthString<M> : string : string;
65
+ type ConstraintsResultTypeWhenMaxLengthIsOn<C extends RawConstraints> = C extends Readonly<{
66
+ maxLength: infer M extends number;
67
+ }> ? [M] extends [SupportedLengthLiteral] ? MaxLengthString<M> : string : string;
68
+ type DefaultValueWhenMinLengthIsOn<S extends string, C extends RawConstraints> = C extends Readonly<{
53
69
  minLength: infer M extends number;
54
- }> ? StringWithMinLength<S, M> : string;
55
- type DefaultValueWhenMaxLengthIsOn<S extends string, C extends Constraints> = C extends Readonly<{
70
+ }> ? [M] extends [SupportedLengthLiteral] ? StringWithMinLength<S, M> : string : string;
71
+ type DefaultValueWhenMaxLengthIsOn<S extends string, C extends RawConstraints> = C extends Readonly<{
56
72
  maxLength: infer M extends number;
57
- }> ? StringWithMaxLength<S, M> : string;
73
+ }> ? [M] extends [SupportedLengthLiteral] ? StringWithMaxLength<S, M> : string : string;
58
74
  type StringWithMinLength<S extends string, N extends number> = HasLengthAtLeast<S, N> extends true ? S : never;
59
75
  type StringWithMaxLength<S extends string, N extends number> = HasLengthAtMost<S, N> extends true ? S : never;
60
- type HasLengthAtLeast<S extends string, N extends number, Acc extends readonly unknown[] = readonly []> = string extends S ? true : IsNegative<N> extends true ? true : Acc['length'] extends N ? true : S extends '' ? false : S extends `${infer _}${infer Rest}` ? HasLengthAtLeast<Rest, N, readonly [...Acc, unknown]> : false;
61
- type HasLengthAtMost<S extends string, N extends number, Acc extends readonly unknown[] = readonly []> = string extends S ? true : IsNegative<N> extends true ? false : S extends '' ? true : Acc['length'] extends N ? false : S extends `${infer _}${infer Rest}` ? HasLengthAtMost<Rest, N, readonly [...Acc, unknown]> : false;
62
- type IsNegative<N extends number> = `${N}` extends `-${string}` ? true : false;
76
+ type HasLengthAtLeast<S extends string, N extends number, Acc extends readonly unknown[] = readonly []> = string extends S ? true : Acc['length'] extends N ? true : S extends '' ? false : S extends `${infer _}${infer Rest}` ? HasLengthAtLeast<Rest, N, readonly [...Acc, unknown]> : false;
77
+ type HasLengthAtMost<S extends string, N extends number, Acc extends readonly unknown[] = readonly []> = string extends S ? true : S extends '' ? true : Acc['length'] extends N ? false : S extends `${infer _}${infer Rest}` ? HasLengthAtMost<Rest, N, readonly [...Acc, unknown]> : false;
63
78
  export {};
64
79
  //# sourceMappingURL=string.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.mts","sourceRoot":"","sources":["../../src/primitives/string.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"string.d.mts","sourceRoot":"","sources":["../../src/primitives/string.mts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { isRegExp } from '@sindresorhus/is';
2
- import { isString, Arr, Result } from 'ts-data-forge';
2
+ import { isString, Arr, Result, PositiveInt } from 'ts-data-forge';
3
3
  import { createPrimitiveType } from '../utils/create-primitive-type.mjs';
4
4
  import { refine } from '../other-types/refine.mjs';
5
5
  import '../other-types/unknown.mjs';
@@ -14,7 +14,11 @@ function string(defaultValue = '', constraints) {
14
14
  Arr.isArrayOfLength(Object.keys(constraints), 0)) {
15
15
  return baseType;
16
16
  }
17
- const constraintsPredicate = createConstraintsPredicate(constraints);
17
+ const constraintsResult = validateConstraints(constraints);
18
+ if (Result.isErr(constraintsResult)) {
19
+ throw new TypeError(constraintsResult.value);
20
+ }
21
+ const constraintsPredicate = createConstraintsPredicate(constraintsResult.value);
18
22
  const defaultValueConstraintsCheck = constraintsPredicate(defaultValue);
19
23
  if (Result.isErr(defaultValueConstraintsCheck)) {
20
24
  throw new Error(defaultValueConstraintsCheck.value);
@@ -26,6 +30,24 @@ function string(defaultValue = '', constraints) {
26
30
  typeName: 'string',
27
31
  });
28
32
  }
33
+ const validateConstraints = (constraints) => {
34
+ const result1 = validateLengthConstraint('minLength', constraints.minLength);
35
+ if (Result.isErr(result1)) {
36
+ return Result.err(result1.value);
37
+ }
38
+ const result2 = validateLengthConstraint('maxLength', constraints.maxLength);
39
+ if (Result.isErr(result2)) {
40
+ return Result.err(result2.value);
41
+ }
42
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
43
+ return Result.ok(constraints);
44
+ };
45
+ const validateLengthConstraint = (constraintName, constraintValue) => {
46
+ if (constraintValue !== undefined && !PositiveInt.is(constraintValue)) {
47
+ return Result.err(`${constraintName} constraint for string must be a positive integer, but ${constraintValue} was passed.`);
48
+ }
49
+ return Result.ok(true);
50
+ };
29
51
  const createConstraintsPredicate = (constraints) => (value) => {
30
52
  const { nonempty, minLength, maxLength, startsWith, endsWith, includes, uppercase, lowercase, regex, ..._rest } = constraints;
31
53
  if (nonempty === true && value.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"string.mjs","sources":["../../src/primitives/string.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"string.mjs","sources":["../../src/primitives/string.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-fortress",
3
- "version": "8.5.2",
3
+ "version": "9.0.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript"
@@ -76,8 +76,8 @@
76
76
  },
77
77
  "dependencies": {
78
78
  "@sindresorhus/is": "^8.1.0",
79
- "ts-data-forge": "^7.1.1",
80
- "ts-type-forge": "^4.0.0"
79
+ "ts-data-forge": "^9.0.0",
80
+ "ts-type-forge": "^5.0.0"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@rollup/plugin-replace": "6.0.3",
@@ -1,10 +1,11 @@
1
- import { type Brand } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
2
2
  import { brand } from '../../../brand/index.mjs';
3
3
  import { string } from '../../../primitives/index.mjs';
4
4
  import { type Type } from '../../../type.mjs';
5
5
 
6
- // A valid e-mail address is always non-empty, so it also satisfies `NonEmptyString`.
7
- export type Email = Brand<string, 'Email' | 'NonEmptyString'>;
6
+ // A valid e-mail address is always non-empty, so `Email` is branded on top of
7
+ // `NonEmptyString` and is assignable to it.
8
+ export type Email = Brand<NonEmptyString, 'Email'>;
8
9
 
9
10
  /**
10
11
  * @link https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
@@ -16,11 +17,12 @@ export const email = (
16
17
  }>
17
18
  >,
18
19
  ): Type<Email> =>
19
- brand({
20
- baseType: string(options?.defaultValue ?? defaultEmail),
20
+ brand<NonEmptyString, readonly ['Email']>({
21
+ baseType: string(options?.defaultValue ?? defaultEmail, {
22
+ nonempty: true,
23
+ }),
21
24
  is: (s): s is Email => regexpEmailAddress.test(s),
22
- defaultValue: options?.defaultValue ?? defaultEmail,
23
- brandKeys: ['Email', 'NonEmptyString'],
25
+ brandKeys: ['Email'],
24
26
  typeName: 'Email',
25
27
  });
26
28
 
@@ -1,12 +1,16 @@
1
- import { type Brand, type StrictOmit } from 'ts-type-forge';
1
+ import {
2
+ type Brand,
3
+ type NonEmptyString,
4
+ type StrictOmit,
5
+ } from 'ts-type-forge';
2
6
  import { brand } from '../../../brand/index.mjs';
3
7
  import { boolean, string } from '../../../primitives/index.mjs';
4
8
  import { record } from '../../../record/index.mjs';
5
9
  import { type Type, type TypeOf } from '../../../type.mjs';
6
10
 
7
- // A valid ISO 8601 string always begins with a 4-digit year, so it is always
8
- // non-empty and also satisfies `NonEmptyString`.
9
- export type Iso8601 = Brand<string, 'Iso8601' | 'NonEmptyString'>;
11
+ // A valid ISO 8601 string always begins with a 4-digit year, so `Iso8601` is
12
+ // branded on top of `NonEmptyString` and is assignable to it.
13
+ export type Iso8601 = Brand<NonEmptyString, 'Iso8601'>;
10
14
 
11
15
  /**
12
16
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
@@ -18,11 +22,10 @@ export const iso8601 = (options?: ISO8601ValidatorOption): Type<Iso8601> => {
18
22
 
19
23
  const is = isISO8601(filledOptions);
20
24
 
21
- return brand({
22
- baseType: string(filledOptions.defaultValue),
25
+ return brand<NonEmptyString, readonly ['Iso8601']>({
26
+ baseType: string(filledOptions.defaultValue, { nonempty: true }),
23
27
  is,
24
- defaultValue: filledOptions.defaultValue,
25
- brandKeys: ['Iso8601', 'NonEmptyString'],
28
+ brandKeys: ['Iso8601'],
26
29
  typeName: 'Iso8601',
27
30
  });
28
31
  };
@@ -1,12 +1,12 @@
1
1
  import { isNonNullObject } from 'ts-data-forge';
2
- import { type Brand } from 'ts-type-forge';
2
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
3
3
  import { brand } from '../../../brand/index.mjs';
4
4
  import { string } from '../../../primitives/index.mjs';
5
5
  import { type Type } from '../../../type.mjs';
6
6
 
7
- // A valid JSON string (an object or array literal) is always non-empty, so it
8
- // also satisfies `NonEmptyString`.
9
- export type JsonString = Brand<string, 'JsonString' | 'NonEmptyString'>;
7
+ // A valid JSON string (an object or array literal) is always non-empty, so
8
+ // `JsonString` is branded on top of `NonEmptyString` and is assignable to it.
9
+ export type JsonString = Brand<NonEmptyString, 'JsonString'>;
10
10
 
11
11
  /**
12
12
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
@@ -18,11 +18,12 @@ export const jsonString = (
18
18
  }>
19
19
  >,
20
20
  ): Type<JsonString> =>
21
- brand({
22
- baseType: string(options?.defaultValue ?? defaultJsonString),
21
+ brand<NonEmptyString, readonly ['JsonString']>({
22
+ baseType: string(options?.defaultValue ?? defaultJsonString, {
23
+ nonempty: true,
24
+ }),
23
25
  is: isJsonString,
24
- defaultValue: options?.defaultValue ?? defaultJsonString,
25
- brandKeys: ['JsonString', 'NonEmptyString'],
26
+ brandKeys: ['JsonString'],
26
27
  typeName: 'JsonString',
27
28
  });
28
29
 
@@ -1,5 +1,5 @@
1
1
  import { expectType } from 'ts-data-forge';
2
- import { type NonEmptyString } from 'ts-type-forge';
2
+ import { type MinLengthString, type NonEmptyString } from 'ts-type-forge';
3
3
  import { type TypeOf } from '../../../type.mjs';
4
4
  import { type Email } from './email.mjs';
5
5
  import { type Iso8601 } from './iso-8601.mjs';
@@ -57,8 +57,9 @@ describe('nonEmptyString with extra constraints', () => {
57
57
  test('forwards constraints to string and still enforces non-emptiness', () => {
58
58
  const t = nonEmptyString('abcd', { minLength: 3 });
59
59
 
60
- // Non-refining constraints (e.g. `minLength`) keep a plain `NonEmptyString`.
61
- expectType<TypeOf<typeof t>, NonEmptyString>('=');
60
+ // Length constraints (e.g. `minLength`) refine the result type with the
61
+ // corresponding length-constrained brand.
62
+ expectType<TypeOf<typeof t>, NonEmptyString & MinLengthString<3>>('=');
62
63
 
63
64
  assert.isTrue(t.is('abcd'));
64
65
 
@@ -1,10 +1,11 @@
1
- import { type Brand } from 'ts-type-forge';
1
+ import { type Brand, type NonEmptyString } from 'ts-type-forge';
2
2
  import { brand } from '../../../brand/index.mjs';
3
3
  import { string } from '../../../primitives/index.mjs';
4
4
  import { type Type } from '../../../type.mjs';
5
5
 
6
- // An absolute URI/URL always has a non-empty scheme, so it also satisfies `NonEmptyString`.
7
- export type Uri = Brand<string, 'Uri' | 'NonEmptyString'>;
6
+ // An absolute URI/URL always has a non-empty scheme, so `Uri` is branded on
7
+ // top of `NonEmptyString` and is assignable to it.
8
+ export type Uri = Brand<NonEmptyString, 'Uri'>;
8
9
 
9
10
  /**
10
11
  * @link https://url.spec.whatwg.org/
@@ -16,11 +17,10 @@ export const uri = (
16
17
  }>
17
18
  >,
18
19
  ): Type<Uri> =>
19
- brand({
20
- baseType: string(options?.defaultValue ?? defaultUri),
20
+ brand<NonEmptyString, readonly ['Uri']>({
21
+ baseType: string(options?.defaultValue ?? defaultUri, { nonempty: true }),
21
22
  is: isUri,
22
- defaultValue: options?.defaultValue ?? defaultUri,
23
- brandKeys: ['Uri', 'NonEmptyString'],
23
+ brandKeys: ['Uri'],
24
24
  typeName: 'Uri',
25
25
  });
26
26
 
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  type Brand,
3
+ type NonEmptyString,
3
4
  type ReadonlyRecord,
4
5
  type TypeEq,
5
6
  type UintRangeInclusive,
@@ -16,14 +17,15 @@ export type UuidBaseString<V extends UuidVersion = UuidVersion> =
16
17
  | 'ffffffff-ffff-ffff-ffff-ffffffffffff';
17
18
 
18
19
  // A UUID always has the dash-separated hexadecimal form, so it is never an
19
- // empty string and also satisfies `NonEmptyString`.
20
- export type Uuid = Brand<UuidBaseString, 'Uuid' | 'NonEmptyString'>;
20
+ // empty string; `Uuid` is branded on top of `NonEmptyString` and is
21
+ // assignable to it.
22
+ export type Uuid = Brand<UuidBaseString & NonEmptyString, 'Uuid'>;
21
23
 
22
- export type Uuid4 = Brand<UuidBaseString<4>, 'Uuid' | 'NonEmptyString'>;
24
+ export type Uuid4 = Brand<UuidBaseString<4> & NonEmptyString, 'Uuid'>;
23
25
 
24
- export type Uuid6 = Brand<UuidBaseString<6>, 'Uuid' | 'NonEmptyString'>;
26
+ export type Uuid6 = Brand<UuidBaseString<6> & NonEmptyString, 'Uuid'>;
25
27
 
26
- export type Uuid7 = Brand<UuidBaseString<7>, 'Uuid' | 'NonEmptyString'>;
28
+ export type Uuid7 = Brand<UuidBaseString<7> & NonEmptyString, 'Uuid'>;
27
29
 
28
30
  /**
29
31
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
@@ -31,20 +33,22 @@ export type Uuid7 = Brand<UuidBaseString<7>, 'Uuid' | 'NonEmptyString'>;
31
33
  export const uuid = <V extends UuidVersion | UuidVersionAdditionalOption>(
32
34
  options?: UuidValidatorOption<V>,
33
35
  ): Type<UuidOf<V>> => {
34
- type T = Brand<UuidBaseString, 'Uuid' | 'NonEmptyString'>;
36
+ type T = Brand<UuidBaseString & NonEmptyString, 'Uuid'>;
35
37
 
36
38
  const defaultValue = options?.defaultValue ?? nilUuid;
37
39
 
38
40
  const version = options?.version ?? 'all';
39
41
 
40
42
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
41
- return brand<UuidBaseString, readonly ['Uuid', 'NonEmptyString']>({
43
+ return brand<UuidBaseString & NonEmptyString, readonly ['Uuid']>({
42
44
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
43
- baseType: string(defaultValue) as Type<UuidBaseString>,
45
+ baseType: string(defaultValue, { nonempty: true }) as Type<
46
+ UuidBaseString & NonEmptyString
47
+ >,
44
48
  is: (s): s is T => uuidDef[version](s),
45
49
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
46
- defaultValue: defaultValue as UuidBaseString,
47
- brandKeys: ['Uuid', 'NonEmptyString'],
50
+ defaultValue: defaultValue as UuidBaseString & NonEmptyString,
51
+ brandKeys: ['Uuid'],
48
52
  typeName:
49
53
  options?.typeName ??
50
54
  (version === 4
@@ -1,18 +1,23 @@
1
1
  import { isRegExp } from '@sindresorhus/is';
2
- import { Arr, expectType, isString, Result } from 'ts-data-forge';
3
- import { type NonEmptyString } from 'ts-type-forge';
2
+ import { Arr, expectType, isString, PositiveInt, Result } from 'ts-data-forge';
3
+ import {
4
+ type MaxLengthString,
5
+ type MinLengthString,
6
+ type NonEmptyString,
7
+ type SmallInt,
8
+ } from 'ts-type-forge';
4
9
  import { refine } from '../other-types/index.mjs';
5
10
  import { type Type } from '../type.mjs';
6
11
  import { createPrimitiveType } from '../utils/index.mjs';
7
12
 
8
13
  export function string(defaultValue?: string): Type<string>;
9
14
 
10
- export function string<S extends string, const C extends Constraints>(
15
+ export function string<S extends string, const C extends RawConstraints>(
11
16
  defaultValue: S & DefaultValueType<S, C>,
12
17
  constraints: C,
13
18
  ): Type<ConstraintsResultType<C>>;
14
19
 
15
- export function string<C extends Constraints>(
20
+ export function string<C extends RawConstraints>(
16
21
  defaultValue: string = '',
17
22
  constraints?: C,
18
23
  ): Type<string> {
@@ -29,7 +34,15 @@ export function string<C extends Constraints>(
29
34
  return baseType;
30
35
  }
31
36
 
32
- const constraintsPredicate = createConstraintsPredicate(constraints);
37
+ const constraintsResult = validateConstraints(constraints);
38
+
39
+ if (Result.isErr(constraintsResult)) {
40
+ throw new TypeError(constraintsResult.value);
41
+ }
42
+
43
+ const constraintsPredicate = createConstraintsPredicate(
44
+ constraintsResult.value,
45
+ );
33
46
 
34
47
  const defaultValueConstraintsCheck = constraintsPredicate(defaultValue);
35
48
 
@@ -45,7 +58,7 @@ export function string<C extends Constraints>(
45
58
  });
46
59
  }
47
60
 
48
- type Constraints = Partial<
61
+ type RawConstraints = Partial<
49
62
  Readonly<{
50
63
  nonempty: true;
51
64
  minLength: number;
@@ -59,22 +72,37 @@ type Constraints = Partial<
59
72
  }>
60
73
  >;
61
74
 
75
+ type Constraints = Partial<
76
+ Readonly<{
77
+ nonempty: true;
78
+ minLength: PositiveInt;
79
+ maxLength: PositiveInt;
80
+ startsWith: string;
81
+ endsWith: string;
82
+ includes: string;
83
+ uppercase: true;
84
+ lowercase: true;
85
+ regex: RegExp;
86
+ }>
87
+ >;
88
+
62
89
  /**
63
90
  * The set of constraints accepted by {@link string}.
64
91
  */
65
- export type StringTypeConstraints = Constraints;
92
+ export type StringTypeConstraints = RawConstraints;
66
93
 
67
94
  /**
68
95
  * The result type produced by {@link string} for a given set of constraints
69
- * `C` (e.g. `nonempty` yields {@link NonEmptyString}, `startsWith` narrows to a
70
- * template literal type, etc.).
96
+ * `C` (e.g. `nonempty` yields {@link NonEmptyString}, `minLength` /
97
+ * `maxLength` yield {@link MinLengthString} / {@link MaxLengthString},
98
+ * `startsWith` narrows to a template literal type, etc.).
71
99
  */
72
100
  export type StringConstraintsResultType<C extends StringTypeConstraints> =
73
101
  ConstraintsResultType<C>;
74
102
 
75
103
  type DefaultValueType<
76
104
  S extends string,
77
- C extends Constraints,
105
+ C extends RawConstraints,
78
106
  > = DefaultValueWhenNonemptyIsOn<S, C> &
79
107
  DefaultValueWhenMinLengthIsOn<S, C> &
80
108
  DefaultValueWhenMaxLengthIsOn<S, C> &
@@ -84,59 +112,89 @@ type DefaultValueType<
84
112
  DefaultValueWhenUppercaseIsOn<S, C> &
85
113
  DefaultValueWhenLowercaseIsOn<S, C>;
86
114
 
87
- type ConstraintsResultType<C extends Constraints> =
115
+ type ConstraintsResultType<C extends RawConstraints> =
88
116
  ConstraintsResultTypeWhenNonemptyIsOn<C> &
117
+ ConstraintsResultTypeWhenMinLengthIsOn<C> &
118
+ ConstraintsResultTypeWhenMaxLengthIsOn<C> &
89
119
  DefaultValueWhenStartsWithIsOn<C> &
90
120
  DefaultValueWhenEndsWithIsOn<C> &
91
121
  DefaultValueWhenIncludesIsOn<C>;
92
122
 
93
- type DefaultValueWhenStartsWithIsOn<C extends Constraints> =
123
+ type DefaultValueWhenStartsWithIsOn<C extends RawConstraints> =
94
124
  C extends Readonly<{
95
125
  startsWith: infer S extends string;
96
126
  }>
97
127
  ? `${S}${string}`
98
128
  : string;
99
129
 
100
- type DefaultValueWhenEndsWithIsOn<C extends Constraints> =
130
+ type DefaultValueWhenEndsWithIsOn<C extends RawConstraints> =
101
131
  C extends Readonly<{
102
132
  endsWith: infer E extends string;
103
133
  }>
104
134
  ? `${string}${E}`
105
135
  : string;
106
136
 
107
- type DefaultValueWhenIncludesIsOn<C extends Constraints> =
137
+ type DefaultValueWhenIncludesIsOn<C extends RawConstraints> =
108
138
  C extends Readonly<{
109
139
  includes: infer M extends string;
110
140
  }>
111
141
  ? `${string}${M}${string}`
112
142
  : string;
113
143
 
114
- type DefaultValueWhenUppercaseIsOn<S extends string, C extends Constraints> =
144
+ type DefaultValueWhenUppercaseIsOn<S extends string, C extends RawConstraints> =
115
145
  C extends Readonly<{ uppercase: true }> ? CastUppercase<S> : string;
116
146
 
117
- type DefaultValueWhenLowercaseIsOn<S extends string, C extends Constraints> =
147
+ type DefaultValueWhenLowercaseIsOn<S extends string, C extends RawConstraints> =
118
148
  C extends Readonly<{ lowercase: true }> ? CastLowercase<S> : string;
119
149
 
120
150
  type CastLowercase<S extends string> = S extends Lowercase<S> ? S : never;
121
151
 
122
152
  type CastUppercase<S extends string> = S extends Uppercase<S> ? S : never;
123
153
 
124
- type DefaultValueWhenNonemptyIsOn<S extends string, C extends Constraints> =
154
+ type DefaultValueWhenNonemptyIsOn<S extends string, C extends RawConstraints> =
125
155
  C extends Readonly<{ nonempty: true }> ? RejectEmptyString<S> : string;
126
156
 
127
157
  type RejectEmptyString<S extends string> = S extends '' ? never : S;
128
158
 
129
- type ConstraintsResultTypeWhenNonemptyIsOn<C extends Constraints> =
159
+ type ConstraintsResultTypeWhenNonemptyIsOn<C extends RawConstraints> =
130
160
  C extends Readonly<{ nonempty: true }> ? NonEmptyString : string;
131
161
 
132
- type DefaultValueWhenMinLengthIsOn<S extends string, C extends Constraints> =
162
+ /**
163
+ * The length-bound literals supported at the type level: `SmallInt<'>0'>`
164
+ * (i.e. `1 | 2 | ... | 39`). Only bounds within this range are encoded in
165
+ * the result brand; larger literals and non-literal `number`s collapse to
166
+ * plain `string` to keep the type-level computation cheap (the runtime
167
+ * constraint applies regardless). Non-integer bounds and bounds less than 1
168
+ * throw a `TypeError` when the type is constructed.
169
+ */
170
+ type SupportedLengthLiteral = SmallInt<'>0'>;
171
+
172
+ type ConstraintsResultTypeWhenMinLengthIsOn<C extends RawConstraints> =
133
173
  C extends Readonly<{ minLength: infer M extends number }>
134
- ? StringWithMinLength<S, M>
174
+ ? [M] extends [SupportedLengthLiteral]
175
+ ? MinLengthString<M>
176
+ : string // minLength outside the supported literal range is not encoded in the brand
135
177
  : string;
136
178
 
137
- type DefaultValueWhenMaxLengthIsOn<S extends string, C extends Constraints> =
179
+ type ConstraintsResultTypeWhenMaxLengthIsOn<C extends RawConstraints> =
138
180
  C extends Readonly<{ maxLength: infer M extends number }>
139
- ? StringWithMaxLength<S, M>
181
+ ? [M] extends [SupportedLengthLiteral]
182
+ ? MaxLengthString<M>
183
+ : string // maxLength outside the supported literal range is not encoded in the brand
184
+ : string;
185
+
186
+ type DefaultValueWhenMinLengthIsOn<S extends string, C extends RawConstraints> =
187
+ C extends Readonly<{ minLength: infer M extends number }>
188
+ ? [M] extends [SupportedLengthLiteral]
189
+ ? StringWithMinLength<S, M>
190
+ : string // the default's length is only checked at runtime for such bounds
191
+ : string;
192
+
193
+ type DefaultValueWhenMaxLengthIsOn<S extends string, C extends RawConstraints> =
194
+ C extends Readonly<{ maxLength: infer M extends number }>
195
+ ? [M] extends [SupportedLengthLiteral]
196
+ ? StringWithMaxLength<S, M>
197
+ : string // the default's length is only checked at runtime for such bounds
140
198
  : string;
141
199
 
142
200
  type StringWithMinLength<S extends string, N extends number> =
@@ -151,15 +209,13 @@ type HasLengthAtLeast<
151
209
  Acc extends readonly unknown[] = readonly [],
152
210
  > = string extends S
153
211
  ? true
154
- : IsNegative<N> extends true
212
+ : Acc['length'] extends N
155
213
  ? true
156
- : Acc['length'] extends N
157
- ? true
158
- : S extends ''
159
- ? false
160
- : S extends `${infer _}${infer Rest}`
161
- ? HasLengthAtLeast<Rest, N, readonly [...Acc, unknown]>
162
- : false;
214
+ : S extends ''
215
+ ? false
216
+ : S extends `${infer _}${infer Rest}`
217
+ ? HasLengthAtLeast<Rest, N, readonly [...Acc, unknown]>
218
+ : false;
163
219
 
164
220
  type HasLengthAtMost<
165
221
  S extends string,
@@ -167,17 +223,45 @@ type HasLengthAtMost<
167
223
  Acc extends readonly unknown[] = readonly [],
168
224
  > = string extends S
169
225
  ? true
170
- : IsNegative<N> extends true
171
- ? false
172
- : S extends ''
173
- ? true
174
- : Acc['length'] extends N
175
- ? false
176
- : S extends `${infer _}${infer Rest}`
177
- ? HasLengthAtMost<Rest, N, readonly [...Acc, unknown]>
178
- : false;
179
-
180
- type IsNegative<N extends number> = `${N}` extends `-${string}` ? true : false;
226
+ : S extends ''
227
+ ? true
228
+ : Acc['length'] extends N
229
+ ? false
230
+ : S extends `${infer _}${infer Rest}`
231
+ ? HasLengthAtMost<Rest, N, readonly [...Acc, unknown]>
232
+ : false;
233
+
234
+ const validateConstraints = (
235
+ constraints: RawConstraints,
236
+ ): Result<Constraints, string> => {
237
+ const result1 = validateLengthConstraint('minLength', constraints.minLength);
238
+
239
+ if (Result.isErr(result1)) {
240
+ return Result.err(result1.value);
241
+ }
242
+
243
+ const result2 = validateLengthConstraint('maxLength', constraints.maxLength);
244
+
245
+ if (Result.isErr(result2)) {
246
+ return Result.err(result2.value);
247
+ }
248
+
249
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
250
+ return Result.ok(constraints as Constraints);
251
+ };
252
+
253
+ const validateLengthConstraint = (
254
+ constraintName: 'maxLength' | 'minLength',
255
+ constraintValue: number | undefined,
256
+ ): Result<true, string> => {
257
+ if (constraintValue !== undefined && !PositiveInt.is(constraintValue)) {
258
+ return Result.err(
259
+ `${constraintName} constraint for string must be a positive integer, but ${constraintValue} was passed.`,
260
+ );
261
+ }
262
+
263
+ return Result.ok(true);
264
+ };
181
265
 
182
266
  const createConstraintsPredicate =
183
267
  (constraints: Constraints) =>
@@ -1,7 +1,12 @@
1
1
  /* cSpell:disable */
2
2
 
3
3
  import { expectType, Result } from 'ts-data-forge';
4
- import { type NonEmptyString } from 'ts-type-forge';
4
+ import {
5
+ type BoundedLengthString,
6
+ type MaxLengthString,
7
+ type MinLengthString,
8
+ type NonEmptyString,
9
+ } from 'ts-type-forge';
5
10
  import { type Type, type TypeOf } from '../type.mjs';
6
11
  import { string } from './string.mjs';
7
12
 
@@ -380,7 +385,7 @@ describe('string with constraints', () => {
380
385
  test('accepts valid default value', () => {
381
386
  const type = string('minimum', { minLength: 3 });
382
387
 
383
- expectType<typeof type, Type<string>>('=');
388
+ expectType<typeof type, Type<MinLengthString<3>>>('=');
384
389
 
385
390
  assert.isTrue(type.is('hello'));
386
391
 
@@ -396,14 +401,20 @@ describe('string with constraints', () => {
396
401
  );
397
402
  });
398
403
 
399
- test('negative minLength', () => {
400
- const type = string('minimum', { minLength: -1 });
401
-
402
- expectType<typeof type, Type<string>>('=');
404
+ test('throws for a minLength less than 1', () => {
405
+ expect(() => string('minimum', { minLength: -1 })).toThrow(
406
+ /^minLength constraint for string must be a positive integer, but -1 was passed\.$/u,
407
+ );
403
408
 
404
- assert.isTrue(type.is('hello'));
409
+ expect(() => string('minimum', { minLength: 0 })).toThrow(
410
+ /^minLength constraint for string must be a positive integer, but 0 was passed\.$/u,
411
+ );
412
+ });
405
413
 
406
- assert.isTrue(type.is('hi'));
414
+ test('throws for a non-integer minLength', () => {
415
+ expect(() => string('minimum', { minLength: 1.5 })).toThrow(
416
+ /^minLength constraint for string must be a positive integer, but 1\.5 was passed\.$/u,
417
+ );
407
418
  });
408
419
  });
409
420
 
@@ -411,7 +422,7 @@ describe('string with constraints', () => {
411
422
  test('accepts valid default value', () => {
412
423
  const type = string('short', { maxLength: 5 });
413
424
 
414
- expectType<typeof type, Type<string>>('=');
425
+ expectType<typeof type, Type<MaxLengthString<5>>>('=');
415
426
 
416
427
  assert.isTrue(type.is('tiny'));
417
428
 
@@ -428,6 +439,76 @@ describe('string with constraints', () => {
428
439
  });
429
440
  });
430
441
 
442
+ describe('minLength/maxLength outside the supported literal range', () => {
443
+ // Only the number literals `1..39` (`SmallInt<'>0'>`) are encoded in the
444
+ // result brand. A larger literal or a non-literal `number` collapses the
445
+ // result type to plain `string` to keep the type-level computation
446
+ // cheap, while the runtime constraint applies regardless. Non-integer
447
+ // bounds and bounds less than 1 throw at construction time.
448
+
449
+ test('the largest supported literal (39) is encoded in the brand', () => {
450
+ const type = string('x'.repeat(39), { minLength: 39 });
451
+
452
+ expectType<typeof type, Type<MinLengthString<39>>>('=');
453
+
454
+ assert.isTrue(type.is('x'.repeat(39)));
455
+
456
+ assert.isFalse(type.is('x'.repeat(38)));
457
+ });
458
+
459
+ test('a minLength literal outside the range (>= 40) falls back to plain string', () => {
460
+ const type = string('x'.repeat(40), { minLength: 40 });
461
+
462
+ expectType<typeof type, Type<string>>('=');
463
+
464
+ // The runtime constraint still applies.
465
+ assert.isTrue(type.is('x'.repeat(40)));
466
+
467
+ assert.isFalse(type.is('x'.repeat(39)));
468
+ });
469
+
470
+ test('a maxLength literal outside the range (>= 40) falls back to plain string', () => {
471
+ const type = string('', { maxLength: 100 });
472
+
473
+ expectType<typeof type, Type<string>>('=');
474
+
475
+ assert.isTrue(type.is('x'.repeat(100)));
476
+
477
+ assert.isFalse(type.is('x'.repeat(101)));
478
+ });
479
+
480
+ test('throws for a maxLength less than 1 or a non-integer maxLength', () => {
481
+ expect(() => string('', { maxLength: 0 })).toThrow(
482
+ /^maxLength constraint for string must be a positive integer, but 0 was passed\.$/u,
483
+ );
484
+
485
+ expect(() => string('', { maxLength: 2.5 })).toThrow(
486
+ /^maxLength constraint for string must be a positive integer, but 2\.5 was passed\.$/u,
487
+ );
488
+ });
489
+
490
+ test('a non-literal bound falls back to plain string', () => {
491
+ const getBound = (): number => 5;
492
+
493
+ const type = string('', { maxLength: getBound() });
494
+
495
+ expectType<typeof type, Type<string>>('=');
496
+
497
+ assert.isTrue(type.is('12345'));
498
+
499
+ assert.isFalse(type.is('123456'));
500
+ });
501
+
502
+ test('the default value is only length-checked at runtime for an out-of-range bound', () => {
503
+ // With an in-range literal bound, a too-short default is already a
504
+ // compile error; with an out-of-range bound it compiles and the check
505
+ // is deferred to runtime.
506
+ expect(() => string('hi', { minLength: 100 })).toThrow(
507
+ /^defaultValue "hi" for string does not satisfy the constraint minLength = 100$/u,
508
+ );
509
+ });
510
+ });
511
+
431
512
  describe('string constrained by regex', () => {
432
513
  test('accepts valid default value', () => {
433
514
  const numeric = /^\d+$/u;
@@ -556,7 +637,10 @@ describe('string with constraints', () => {
556
637
  maxLength: 8,
557
638
  });
558
639
 
559
- expectType<typeof type, Type<NonEmptyString>>('=');
640
+ expectType<
641
+ typeof type,
642
+ Type<NonEmptyString & BoundedLengthString<3, 8>>
643
+ >('=');
560
644
 
561
645
  assert.isTrue(type.is('value'));
562
646
 
@@ -635,7 +719,7 @@ describe('string with constraints', () => {
635
719
  regex: digits,
636
720
  });
637
721
 
638
- expectType<typeof type, Type<string>>('=');
722
+ expectType<typeof type, Type<BoundedLengthString<4, 6>>>('=');
639
723
 
640
724
  assert.isTrue(type.is('6789'));
641
725
 
@@ -197,8 +197,7 @@ describe(keyValueRecord, () => {
197
197
 
198
198
  assert.isFalse(strNumRecord.is('string'));
199
199
 
200
- // Empty array is actually treated as empty object (valid)
201
- assert.isTrue(strNumRecord.is([]));
200
+ assert.isFalse(strNumRecord.is([]));
202
201
  });
203
202
 
204
203
  test('rejects record with invalid key types', () => {