ts-fortress 6.2.2 → 6.2.4

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 (119) hide show
  1. package/README.md +1 -1
  2. package/dist/array/array-at-least-length.d.mts +2 -2
  3. package/dist/array/array-at-least-length.d.mts.map +1 -1
  4. package/dist/array/array-at-least-length.mjs.map +1 -1
  5. package/dist/array/array-of-length.d.mts +2 -2
  6. package/dist/array/array-of-length.d.mts.map +1 -1
  7. package/dist/array/array-of-length.mjs.map +1 -1
  8. package/dist/array/array.d.mts +2 -2
  9. package/dist/array/array.d.mts.map +1 -1
  10. package/dist/array/array.mjs.map +1 -1
  11. package/dist/array/non-empty-array.d.mts +2 -2
  12. package/dist/array/non-empty-array.d.mts.map +1 -1
  13. package/dist/array/non-empty-array.mjs.map +1 -1
  14. package/dist/array/tuple.d.mts +5 -5
  15. package/dist/array/tuple.d.mts.map +1 -1
  16. package/dist/array/tuple.mjs.map +1 -1
  17. package/dist/brand/brand.d.mts +1 -1
  18. package/dist/brand/brand.d.mts.map +1 -1
  19. package/dist/compose/intersection.d.mts +4 -4
  20. package/dist/compose/intersection.d.mts.map +1 -1
  21. package/dist/compose/intersection.mjs.map +1 -1
  22. package/dist/compose/merge-records.d.mts +3 -3
  23. package/dist/compose/merge-records.d.mts.map +1 -1
  24. package/dist/compose/merge-records.mjs.map +1 -1
  25. package/dist/compose/union.d.mts +2 -2
  26. package/dist/compose/union.d.mts.map +1 -1
  27. package/dist/compose/union.mjs.map +1 -1
  28. package/dist/enum/enum.d.mts +2 -2
  29. package/dist/enum/enum.d.mts.map +1 -1
  30. package/dist/enum/enum.mjs.map +1 -1
  31. package/dist/globals.d.mts +0 -2
  32. package/dist/other-types/map.d.mts +2 -2
  33. package/dist/other-types/map.d.mts.map +1 -1
  34. package/dist/other-types/map.mjs.map +1 -1
  35. package/dist/other-types/recursion.d.mts +2 -2
  36. package/dist/other-types/recursion.d.mts.map +1 -1
  37. package/dist/other-types/recursion.mjs +5 -7
  38. package/dist/other-types/recursion.mjs.map +1 -1
  39. package/dist/other-types/set.d.mts +2 -2
  40. package/dist/other-types/set.d.mts.map +1 -1
  41. package/dist/other-types/set.mjs.map +1 -1
  42. package/dist/predefined/brand/string/email.d.mts +2 -2
  43. package/dist/predefined/brand/string/email.d.mts.map +1 -1
  44. package/dist/predefined/brand/string/email.mjs.map +1 -1
  45. package/dist/predefined/brand/string/json-string.d.mts +2 -2
  46. package/dist/predefined/brand/string/json-string.d.mts.map +1 -1
  47. package/dist/predefined/brand/string/json-string.mjs.map +1 -1
  48. package/dist/predefined/brand/string/uuid.d.mts +2 -2
  49. package/dist/predefined/brand/string/uuid.d.mts.map +1 -1
  50. package/dist/predefined/brand/string/uuid.mjs.map +1 -1
  51. package/dist/primitives/bigint.d.mts +10 -10
  52. package/dist/primitives/bigint.d.mts.map +1 -1
  53. package/dist/primitives/bigint.mjs.map +1 -1
  54. package/dist/primitives/number.d.mts +10 -10
  55. package/dist/primitives/number.d.mts.map +1 -1
  56. package/dist/primitives/number.mjs.map +1 -1
  57. package/dist/primitives/string.d.mts +20 -20
  58. package/dist/primitives/string.d.mts.map +1 -1
  59. package/dist/primitives/string.mjs.map +1 -1
  60. package/dist/record/key-value-record.d.mts +2 -2
  61. package/dist/record/key-value-record.d.mts.map +1 -1
  62. package/dist/record/key-value-record.mjs.map +1 -1
  63. package/dist/record/keyof.d.mts +2 -2
  64. package/dist/record/keyof.d.mts.map +1 -1
  65. package/dist/record/keyof.mjs.map +1 -1
  66. package/dist/record/omit.d.mts +2 -2
  67. package/dist/record/omit.d.mts.map +1 -1
  68. package/dist/record/omit.mjs.map +1 -1
  69. package/dist/record/partial.d.mts +8 -8
  70. package/dist/record/partial.d.mts.map +1 -1
  71. package/dist/record/partial.mjs.map +1 -1
  72. package/dist/record/pick.d.mts +2 -2
  73. package/dist/record/pick.d.mts.map +1 -1
  74. package/dist/record/pick.mjs.map +1 -1
  75. package/dist/record/record.d.mts +4 -4
  76. package/dist/record/record.d.mts.map +1 -1
  77. package/dist/record/record.mjs.map +1 -1
  78. package/dist/record/required.d.mts +8 -8
  79. package/dist/record/required.d.mts.map +1 -1
  80. package/dist/record/required.mjs.map +1 -1
  81. package/dist/record/valueof.d.mts +2 -2
  82. package/dist/record/valueof.d.mts.map +1 -1
  83. package/dist/record/valueof.mjs.map +1 -1
  84. package/dist/type.d.mts +4 -4
  85. package/dist/type.d.mts.map +1 -1
  86. package/package.json +26 -19
  87. package/src/array/array-at-least-length.mts +6 -4
  88. package/src/array/array-of-length.mts +6 -4
  89. package/src/array/array.mts +6 -4
  90. package/src/array/non-empty-array.mts +6 -4
  91. package/src/array/tuple.mts +8 -6
  92. package/src/brand/brand.mts +1 -1
  93. package/src/compose/intersection.mts +76 -59
  94. package/src/compose/merge-records.mts +74 -59
  95. package/src/compose/union-literal-array.test.mts +1 -1
  96. package/src/compose/union-nested-record.test.mts +10 -8
  97. package/src/compose/union-records.test.mts +10 -8
  98. package/src/compose/union.mts +18 -8
  99. package/src/enum/enum.mts +6 -4
  100. package/src/globals.d.mts +0 -2
  101. package/src/other-types/map.mts +5 -3
  102. package/src/other-types/recursion.mts +10 -10
  103. package/src/other-types/recursion.test.mts +1 -1
  104. package/src/other-types/set.mts +5 -3
  105. package/src/predefined/brand/string/email.mts +5 -3
  106. package/src/predefined/brand/string/json-string.mts +5 -3
  107. package/src/predefined/brand/string/uuid.mts +10 -8
  108. package/src/primitives/bigint.mts +24 -30
  109. package/src/primitives/number.mts +24 -30
  110. package/src/primitives/string.mts +53 -58
  111. package/src/record/key-value-record.mts +5 -3
  112. package/src/record/keyof.mts +17 -9
  113. package/src/record/omit.mts +19 -14
  114. package/src/record/partial.mts +25 -18
  115. package/src/record/pick.mts +19 -14
  116. package/src/record/record.mts +28 -24
  117. package/src/record/required.mts +27 -26
  118. package/src/record/valueof.mts +9 -7
  119. package/src/type.mts +9 -15
@@ -23,14 +23,16 @@ describe('union - records only', () => {
23
23
 
24
24
  expectType<
25
25
  TargetType,
26
- | Readonly<{
27
- kind: string;
28
- value: number;
29
- }>
30
- | Readonly<{
31
- type: string;
32
- data: string;
33
- }>
26
+ Readonly<
27
+ | {
28
+ kind: string;
29
+ value: number;
30
+ }
31
+ | {
32
+ type: string;
33
+ data: string;
34
+ }
35
+ >
34
36
  >('=');
35
37
 
36
38
  expectType<typeof targetType.defaultValue, TargetType>('=');
@@ -10,10 +10,12 @@ import {
10
10
 
11
11
  export const union = <const Types extends NonEmptyArray<Type<unknown>>>(
12
12
  types: Types,
13
- options?: PartialReadonly<{
14
- typeName: string;
15
- defaultType: UnionType<Types>;
16
- }>,
13
+ options?: Partial<
14
+ Readonly<{
15
+ typeName: string;
16
+ defaultType: UnionType<Types>;
17
+ }>
18
+ >,
17
19
  ): UnionType<Types> => {
18
20
  type T = UnionTypeValue<Types>;
19
21
 
@@ -70,11 +72,19 @@ namespace TsFortressInternal {
70
72
  }
71
73
 
72
74
  expectType<
73
- UnionType<[Type<{ a: 0; b: 0 }>, Type<{ b: 0; c: 0 }>]>,
74
- Type<{ a: 0; b: 0 } | { b: 0; c: 0 }>
75
+ UnionType<
76
+ readonly [Type<Readonly<{ a: 0; b: 0 }>>, Type<Readonly<{ b: 0; c: 0 }>>]
77
+ >,
78
+ Type<Readonly<{ a: 0; b: 0 } | { b: 0; c: 0 }>>
75
79
  >('=');
76
80
 
77
81
  expectType<
78
- UnionType<[Type<{ a: 0; b: 0 }>, Type<{ b: 0; c: 0 }>, Type<{ e: 0; f: 0 }>]>,
79
- Type<{ a: 0; b: 0 } | { b: 0; c: 0 } | { e: 0; f: 0 }>
82
+ UnionType<
83
+ readonly [
84
+ Type<Readonly<{ a: 0; b: 0 }>>,
85
+ Type<Readonly<{ b: 0; c: 0 }>>,
86
+ Type<Readonly<{ e: 0; f: 0 }>>,
87
+ ]
88
+ >,
89
+ Type<Readonly<{ a: 0; b: 0 } | { b: 0; c: 0 } | { e: 0; f: 0 }>>
80
90
  >('=');
package/src/enum/enum.mts CHANGED
@@ -9,10 +9,12 @@ import {
9
9
 
10
10
  export const enumType = <const Values extends NonEmptyArray<Primitive>>(
11
11
  values: Values,
12
- options?: PartialReadonly<{
13
- typeName: string;
14
- defaultValue: ArrayElement<Values>;
15
- }>,
12
+ options?: Partial<
13
+ Readonly<{
14
+ typeName: string;
15
+ defaultValue: ArrayElement<Values>;
16
+ }>
17
+ >,
16
18
  ): Type<ArrayElement<Values>> => {
17
19
  type T = ArrayElement<Values>;
18
20
 
package/src/globals.d.mts CHANGED
@@ -1,7 +1,5 @@
1
1
  /// <reference types="ts-type-forge" />
2
2
 
3
- type PartialReadonly<T> = Partial<Readonly<T>>;
4
-
5
3
  type Iso8601 = Brand<string, 'Iso8601'>;
6
4
 
7
5
  type Email = Brand<string, 'Email'>;
@@ -20,9 +20,11 @@ type MapResultType<
20
20
  export const MapType = <K extends Type<unknown>, V extends Type<unknown>>(
21
21
  keyType: K,
22
22
  valueType: V,
23
- options?: PartialReadonly<{
24
- typeName: string;
25
- }>,
23
+ options?: Partial<
24
+ Readonly<{
25
+ typeName: string;
26
+ }>
27
+ >,
26
28
  ): Type<MapResultType<K, V>> => {
27
29
  type M = MapResultType<K, V>;
28
30
 
@@ -4,11 +4,13 @@ import { createAssertFn, createCastFn, createIsFn } from '../utils/index.mjs';
4
4
  export const recursion = <A,>(
5
5
  typeName: string,
6
6
  definition: () => Type<A>,
7
- options?: PartialReadonly<{
8
- defaultValue: A;
9
- }>,
7
+ options?: Partial<
8
+ Readonly<{
9
+ defaultValue: A;
10
+ }>
11
+ >,
10
12
  ): Type<A> => {
11
- const cache: {
13
+ const mut_cache: {
12
14
  innerType: Type<A> | undefined;
13
15
  computedDefaultValue: A | undefined;
14
16
  } = {
@@ -17,10 +19,9 @@ export const recursion = <A,>(
17
19
  };
18
20
 
19
21
  const getInnerType = (): Type<A> => {
20
- // eslint-disable-next-line functional/immutable-data
21
- cache.innerType ??= definition();
22
+ mut_cache.innerType ??= definition();
22
23
 
23
- return cache.innerType;
24
+ return mut_cache.innerType;
24
25
  };
25
26
 
26
27
  const validate: Type<A>['validate'] = (a) => getInnerType().validate(a);
@@ -36,10 +37,9 @@ export const recursion = <A,>(
36
37
  return options.defaultValue;
37
38
  }
38
39
 
39
- // eslint-disable-next-line functional/immutable-data
40
- cache.computedDefaultValue ??= getInnerType().defaultValue;
40
+ mut_cache.computedDefaultValue ??= getInnerType().defaultValue;
41
41
 
42
- return cache.computedDefaultValue;
42
+ return mut_cache.computedDefaultValue;
43
43
  },
44
44
  fill,
45
45
  validate,
@@ -183,7 +183,7 @@ describe('recursive', () => {
183
183
 
184
184
  // Test other recursive structures
185
185
  test('Linked list structure', () => {
186
- type LinkedList<T> = { value: T; next: LinkedList<T> | null };
186
+ type LinkedList<T> = Readonly<{ value: T; next: LinkedList<T> | null }>;
187
187
 
188
188
  const LinkedListNumber: Type<LinkedList<number>> = recursion(
189
189
  'LinkedList<number>',
@@ -15,9 +15,11 @@ type SetResultType<T extends Type<unknown>> = ReadonlySet<TypeOf<T>>;
15
15
 
16
16
  export const SetType = <T extends Type<unknown>>(
17
17
  elementType: T,
18
- options?: PartialReadonly<{
19
- typeName: string;
20
- }>,
18
+ options?: Partial<
19
+ Readonly<{
20
+ typeName: string;
21
+ }>
22
+ >,
21
23
  ): Type<SetResultType<T>> => {
22
24
  type S = SetResultType<T>;
23
25
 
@@ -5,9 +5,11 @@ import { type Type } from '../../../type.mjs';
5
5
  * @link https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
6
6
  */
7
7
  export const email = (
8
- options?: PartialReadonly<{
9
- defaultValue: string;
10
- }>,
8
+ options?: Partial<
9
+ Readonly<{
10
+ defaultValue: string;
11
+ }>
12
+ >,
11
13
  ): Type<Email> =>
12
14
  brandedString({
13
15
  is: (s): s is Email => regexpEmailAddress.test(s),
@@ -6,9 +6,11 @@ import { type Type } from '../../../type.mjs';
6
6
  * @link https://github.com/validatorjs/validator.js/tree/v13.1.17?tab=readme-ov-file#validators
7
7
  */
8
8
  export const jsonString = (
9
- options?: PartialReadonly<{
10
- defaultValue: string;
11
- }>,
9
+ options?: Partial<
10
+ Readonly<{
11
+ defaultValue: string;
12
+ }>
13
+ >,
12
14
  ): Type<JsonString> =>
13
15
  brandedString({
14
16
  is: isJsonString,
@@ -64,15 +64,17 @@ export const uuidV7 = (defaultValue?: string): Type<Uuid7> =>
64
64
  });
65
65
 
66
66
  type UuidValidatorOption<V extends UuidVersion | UuidVersionAdditionalOption> =
67
- PartialReadonly<{
68
- /**
69
- * @param version One of 1-8, 'nil', 'max', 'all' or 'loose'. The 'loose' option checks if the string is a UUID-like string with hexadecimal values, ignoring RFC9562.
70
- */
71
- version: V;
67
+ Partial<
68
+ Readonly<{
69
+ /**
70
+ * @param version One of 1-8, 'nil', 'max', 'all' or 'loose'. The 'loose' option checks if the string is a UUID-like string with hexadecimal values, ignoring RFC9562.
71
+ */
72
+ version: V;
72
73
 
73
- typeName: string;
74
- defaultValue: string;
75
- }>;
74
+ typeName: string;
75
+ defaultValue: string;
76
+ }>
77
+ >;
76
78
 
77
79
  const nilUuid = '00000000-0000-0000-0000-000000000000' satisfies UuidBaseString;
78
80
 
@@ -126,20 +126,22 @@ export function bigint<C extends Constraints>(
126
126
  });
127
127
  }
128
128
 
129
- type Constraints = PartialReadonly<{
130
- gt: bigint;
131
- gte: bigint;
132
- min: bigint;
133
- lt: bigint;
134
- lte: bigint;
135
- max: bigint;
136
- negative: boolean;
137
- nonNegative: boolean;
138
- positive: boolean;
139
- nonPositive: boolean;
140
- multipleOf: bigint;
141
- step: bigint;
142
- }>;
129
+ type Constraints = Partial<
130
+ Readonly<{
131
+ gt: bigint;
132
+ gte: bigint;
133
+ min: bigint;
134
+ lt: bigint;
135
+ lte: bigint;
136
+ max: bigint;
137
+ negative: boolean;
138
+ nonNegative: boolean;
139
+ positive: boolean;
140
+ nonPositive: boolean;
141
+ multipleOf: bigint;
142
+ step: bigint;
143
+ }>
144
+ >;
143
145
 
144
146
  type DefaultValueType<
145
147
  B extends bigint,
@@ -149,25 +151,17 @@ type DefaultValueType<
149
151
  DefaultValueWhenPositiveIsOn<B, R> &
150
152
  DefaultValueWhenNonPositiveIsOn<B, R>;
151
153
 
152
- type DefaultValueWhenNegativeIsOn<
153
- B extends bigint,
154
- R extends Constraints,
155
- > = R extends { negative: true } ? NegativeBigint<B> : bigint;
154
+ type DefaultValueWhenNegativeIsOn<B extends bigint, R extends Constraints> =
155
+ R extends Readonly<{ negative: true }> ? NegativeBigint<B> : bigint;
156
156
 
157
- type DefaultValueWhenNonNegativeIsOn<
158
- B extends bigint,
159
- R extends Constraints,
160
- > = R extends { nonNegative: true } ? NonNegativeBigint<B> : bigint;
157
+ type DefaultValueWhenNonNegativeIsOn<B extends bigint, R extends Constraints> =
158
+ R extends Readonly<{ nonNegative: true }> ? NonNegativeBigint<B> : bigint;
161
159
 
162
- type DefaultValueWhenPositiveIsOn<
163
- B extends bigint,
164
- R extends Constraints,
165
- > = R extends { positive: true } ? PositiveBigint<B> : bigint;
160
+ type DefaultValueWhenPositiveIsOn<B extends bigint, R extends Constraints> =
161
+ R extends Readonly<{ positive: true }> ? PositiveBigint<B> : bigint;
166
162
 
167
- type DefaultValueWhenNonPositiveIsOn<
168
- B extends bigint,
169
- R extends Constraints,
170
- > = R extends { nonPositive: true } ? NonPositiveBigint<B> : bigint;
163
+ type DefaultValueWhenNonPositiveIsOn<B extends bigint, R extends Constraints> =
164
+ R extends Readonly<{ nonPositive: true }> ? NonPositiveBigint<B> : bigint;
171
165
 
172
166
  type NegativeBigint<B extends bigint> = bigint extends B
173
167
  ? bigint
@@ -109,20 +109,22 @@ export function number<C extends Constraints>(
109
109
  });
110
110
  }
111
111
 
112
- type Constraints = PartialReadonly<{
113
- gt: number;
114
- gte: number;
115
- min: number;
116
- lt: number;
117
- lte: number;
118
- max: number;
119
- negative: boolean;
120
- nonNegative: boolean;
121
- positive: boolean;
122
- nonPositive: boolean;
123
- multipleOf: number;
124
- step: number;
125
- }>;
112
+ type Constraints = Partial<
113
+ Readonly<{
114
+ gt: number;
115
+ gte: number;
116
+ min: number;
117
+ lt: number;
118
+ lte: number;
119
+ max: number;
120
+ negative: boolean;
121
+ nonNegative: boolean;
122
+ positive: boolean;
123
+ nonPositive: boolean;
124
+ multipleOf: number;
125
+ step: number;
126
+ }>
127
+ >;
126
128
 
127
129
  type DefaultValueType<
128
130
  N extends number,
@@ -132,25 +134,17 @@ type DefaultValueType<
132
134
  DefaultValueWhenPositiveIsOn<N, R> &
133
135
  DefaultValueWhenNonPositiveIsOn<N, R>;
134
136
 
135
- type DefaultValueWhenNegativeIsOn<
136
- N extends number,
137
- R extends Constraints,
138
- > = R extends { negative: true } ? NegativeNumber<N> : number;
137
+ type DefaultValueWhenNegativeIsOn<N extends number, R extends Constraints> =
138
+ R extends Readonly<{ negative: true }> ? NegativeNumber<N> : number;
139
139
 
140
- type DefaultValueWhenNonNegativeIsOn<
141
- N extends number,
142
- R extends Constraints,
143
- > = R extends { nonNegative: true } ? NonNegativeNumber<N> : number;
140
+ type DefaultValueWhenNonNegativeIsOn<N extends number, R extends Constraints> =
141
+ R extends Readonly<{ nonNegative: true }> ? NonNegativeNumber<N> : number;
144
142
 
145
- type DefaultValueWhenPositiveIsOn<
146
- N extends number,
147
- R extends Constraints,
148
- > = R extends { positive: true } ? PositiveNumber<N> : number;
143
+ type DefaultValueWhenPositiveIsOn<N extends number, R extends Constraints> =
144
+ R extends Readonly<{ positive: true }> ? PositiveNumber<N> : number;
149
145
 
150
- type DefaultValueWhenNonPositiveIsOn<
151
- N extends number,
152
- R extends Constraints,
153
- > = R extends { nonPositive: true } ? NonPositiveNumber<N> : number;
146
+ type DefaultValueWhenNonPositiveIsOn<N extends number, R extends Constraints> =
147
+ R extends Readonly<{ nonPositive: true }> ? NonPositiveNumber<N> : number;
154
148
 
155
149
  type NegativeNumber<N extends number> = number extends N
156
150
  ? number
@@ -112,17 +112,19 @@ export function string<C extends Constraints>(
112
112
  });
113
113
  }
114
114
 
115
- type Constraints = PartialReadonly<{
116
- startsWith: string;
117
- endsWith: string;
118
- includes: string;
119
- uppercase: boolean;
120
- lowercase: boolean;
121
- nonempty: boolean;
122
- minLength: number;
123
- maxLength: number;
124
- regex: DeepReadonly<RegExp>;
125
- }>;
115
+ type Constraints = Partial<
116
+ Readonly<{
117
+ startsWith: string;
118
+ endsWith: string;
119
+ includes: string;
120
+ uppercase: boolean;
121
+ lowercase: boolean;
122
+ nonempty: boolean;
123
+ minLength: number;
124
+ maxLength: number;
125
+ regex: DeepReadonly<RegExp>;
126
+ }>
127
+ >;
126
128
 
127
129
  type DefaultValueType<
128
130
  S extends string,
@@ -141,56 +143,49 @@ type ConstraintsResultType<R extends Constraints> =
141
143
  DefaultValueWhenEndsWithIsOn<R> &
142
144
  DefaultValueWhenIncludesIsOn<R>;
143
145
 
144
- type DefaultValueWhenStartsWithIsOn<R extends Constraints> = R extends {
145
- startsWith: infer S extends string;
146
- }
147
- ? `${S}${string}`
148
- : string;
149
-
150
- type DefaultValueWhenEndsWithIsOn<R extends Constraints> = R extends {
151
- endsWith: infer E extends string;
152
- }
153
- ? `${string}${E}`
154
- : string;
155
-
156
- type DefaultValueWhenIncludesIsOn<R extends Constraints> = R extends {
157
- includes: infer M extends string;
158
- }
159
- ? `${string}${M}${string}`
160
- : string;
161
-
162
- type DefaultValueWhenUppercaseIsOn<
163
- S extends string,
164
- R extends Constraints,
165
- > = R extends { uppercase: true } ? CastUppercase<S> : string;
166
-
167
- type DefaultValueWhenLowercaseIsOn<
168
- S extends string,
169
- R extends Constraints,
170
- > = R extends { lowercase: true } ? CastLowercase<S> : string;
146
+ type DefaultValueWhenStartsWithIsOn<R extends Constraints> =
147
+ R extends Readonly<{
148
+ startsWith: infer S extends string;
149
+ }>
150
+ ? `${S}${string}`
151
+ : string;
152
+
153
+ type DefaultValueWhenEndsWithIsOn<R extends Constraints> =
154
+ R extends Readonly<{
155
+ endsWith: infer E extends string;
156
+ }>
157
+ ? `${string}${E}`
158
+ : string;
159
+
160
+ type DefaultValueWhenIncludesIsOn<R extends Constraints> =
161
+ R extends Readonly<{
162
+ includes: infer M extends string;
163
+ }>
164
+ ? `${string}${M}${string}`
165
+ : string;
166
+
167
+ type DefaultValueWhenUppercaseIsOn<S extends string, R extends Constraints> =
168
+ R extends Readonly<{ uppercase: true }> ? CastUppercase<S> : string;
169
+
170
+ type DefaultValueWhenLowercaseIsOn<S extends string, R extends Constraints> =
171
+ R extends Readonly<{ lowercase: true }> ? CastLowercase<S> : string;
171
172
 
172
173
  type CastLowercase<S extends string> = S extends Lowercase<S> ? S : never;
173
174
 
174
175
  type CastUppercase<S extends string> = S extends Uppercase<S> ? S : never;
175
176
 
176
- type DefaultValueWhenNonemptyIsOn<
177
- S extends string,
178
- R extends Constraints,
179
- > = R extends { nonempty: true } ? NonEmptyString<S> : string;
177
+ type DefaultValueWhenNonemptyIsOn<S extends string, R extends Constraints> =
178
+ R extends Readonly<{ nonempty: true }> ? NonEmptyString<S> : string;
180
179
 
181
- type DefaultValueWhenMinLengthIsOn<
182
- S extends string,
183
- R extends Constraints,
184
- > = R extends { minLength: infer M extends number }
185
- ? StringWithMinLength<S, M>
186
- : string;
180
+ type DefaultValueWhenMinLengthIsOn<S extends string, R extends Constraints> =
181
+ R extends Readonly<{ minLength: infer M extends number }>
182
+ ? StringWithMinLength<S, M>
183
+ : string;
187
184
 
188
- type DefaultValueWhenMaxLengthIsOn<
189
- S extends string,
190
- R extends Constraints,
191
- > = R extends { maxLength: infer M extends number }
192
- ? StringWithMaxLength<S, M>
193
- : string;
185
+ type DefaultValueWhenMaxLengthIsOn<S extends string, R extends Constraints> =
186
+ R extends Readonly<{ maxLength: infer M extends number }>
187
+ ? StringWithMaxLength<S, M>
188
+ : string;
194
189
 
195
190
  type NonEmptyString<S extends string> = string extends S
196
191
  ? string
@@ -207,7 +202,7 @@ type StringWithMaxLength<S extends string, N extends number> =
207
202
  type HasLengthAtLeast<
208
203
  S extends string,
209
204
  N extends number,
210
- Acc extends unknown[] = [],
205
+ Acc extends readonly unknown[] = readonly [],
211
206
  > = string extends S
212
207
  ? true
213
208
  : IsNegative<N> extends true
@@ -217,13 +212,13 @@ type HasLengthAtLeast<
217
212
  : S extends ''
218
213
  ? false
219
214
  : S extends `${infer _}${infer Rest}`
220
- ? HasLengthAtLeast<Rest, N, [...Acc, unknown]>
215
+ ? HasLengthAtLeast<Rest, N, readonly [...Acc, unknown]>
221
216
  : false;
222
217
 
223
218
  type HasLengthAtMost<
224
219
  S extends string,
225
220
  N extends number,
226
- Acc extends unknown[] = [],
221
+ Acc extends readonly unknown[] = readonly [],
227
222
  > = string extends S
228
223
  ? true
229
224
  : IsNegative<N> extends true
@@ -233,7 +228,7 @@ type HasLengthAtMost<
233
228
  : Acc['length'] extends N
234
229
  ? false
235
230
  : S extends `${infer _}${infer Rest}`
236
- ? HasLengthAtMost<Rest, N, [...Acc, unknown]>
231
+ ? HasLengthAtMost<Rest, N, readonly [...Acc, unknown]>
237
232
  : false;
238
233
 
239
234
  type IsNegative<N extends number> = `${N}` extends `-${string}` ? true : false;
@@ -17,9 +17,11 @@ type RecordResultType<
17
17
  export const keyValueRecord = <K extends Type<string>, V extends Type<unknown>>(
18
18
  keyType: K,
19
19
  valueType: V,
20
- options?: PartialReadonly<{
21
- typeName: string;
22
- }>,
20
+ options?: Partial<
21
+ Readonly<{
22
+ typeName: string;
23
+ }>
24
+ >,
23
25
  ): Type<RecordResultType<K, V>> => {
24
26
  type T = RecordResultType<K, V>;
25
27
 
@@ -5,9 +5,11 @@ import { type RecordType, type Type } from '../type.mjs';
5
5
 
6
6
  export const keyof = <const R extends ReadonlyRecord<string, Type<unknown>>>(
7
7
  recordType: RecordType<R>,
8
- options?: PartialReadonly<{
9
- typeName: string;
10
- }>,
8
+ options?: Partial<
9
+ Readonly<{
10
+ typeName: string;
11
+ }>
12
+ >,
11
13
  ): KeyofType<R> =>
12
14
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
13
15
  pipe(getKeys(recordType)).map((keys) =>
@@ -22,7 +24,11 @@ const getKeys = <const R extends ReadonlyRecord<string, Type<unknown>>>(
22
24
  recordType: RecordType<R>,
23
25
  ): readonly ToString<keyof R>[] =>
24
26
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
25
- Object.keys(recordType.shape) satisfies string[] as ToString<keyof R>[];
27
+ Object.keys(
28
+ recordType.shape,
29
+ ) satisfies readonly string[] as readonly string[] as readonly ToString<
30
+ keyof R
31
+ >[];
26
32
 
27
33
  type KeyofTypeSub<R extends ReadonlyRecord<string, Type<unknown>>> = Type<
28
34
  ToString<keyof R>
@@ -34,24 +40,26 @@ type KeyofType<R extends ReadonlyRecord<string, Type<unknown>>> =
34
40
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
35
41
  expectType<keyof {}, never>('=');
36
42
 
37
- expectType<ToString<keyof { 1: 1; 2: 2; 3: 3 }>, '1' | '2' | '3'>('=');
43
+ expectType<ToString<keyof Readonly<{ 1: 1; 2: 2; 3: 3 }>>, '1' | '2' | '3'>(
44
+ '=',
45
+ );
38
46
 
39
47
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
40
48
  expectType<KeyofType<{}>, Type<undefined>>('=');
41
49
 
42
50
  expectType<
43
- KeyofType<{ a: Type<0>; b: Type<1>; c: Type<2> }>,
51
+ KeyofType<Readonly<{ a: Type<0>; b: Type<1>; c: Type<2> }>>,
44
52
  Type<'a' | 'b' | 'c'>
45
53
  >('=');
46
54
 
47
55
  expectType<
48
- KeyofType<{ x: Type<string>; y: Type<number>; z: Type<boolean> }>,
56
+ KeyofType<Readonly<{ x: Type<string>; y: Type<number>; z: Type<boolean> }>>,
49
57
  Type<'x' | 'y' | 'z'>
50
58
  >('=');
51
59
 
52
60
  expectType<
53
- KeyofType<{ same: Type<string>; value: Type<string> }>,
61
+ KeyofType<Readonly<{ same: Type<string>; value: Type<string> }>>,
54
62
  Type<'same' | 'value'>
55
63
  >('=');
56
64
 
57
- expectType<KeyofType<{ never: Type<never> }>, Type<'never'>>('=');
65
+ expectType<KeyofType<Readonly<{ never: Type<never> }>>, Type<'never'>>('=');