ts-data-forge 1.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.
- package/LICENSE +201 -0
- package/README.md +534 -0
- package/package.json +101 -0
- package/src/array/array-utils-creation.test.mts +443 -0
- package/src/array/array-utils-modification.test.mts +197 -0
- package/src/array/array-utils-overload-type-error.test.mts +149 -0
- package/src/array/array-utils-reducing-value.test.mts +425 -0
- package/src/array/array-utils-search.test.mts +169 -0
- package/src/array/array-utils-set-op.test.mts +335 -0
- package/src/array/array-utils-slice-clamped.test.mts +113 -0
- package/src/array/array-utils-slicing.test.mts +316 -0
- package/src/array/array-utils-transformation.test.mts +790 -0
- package/src/array/array-utils-validation.test.mts +492 -0
- package/src/array/array-utils.mts +4000 -0
- package/src/array/array.test.mts +146 -0
- package/src/array/index.mts +2 -0
- package/src/array/tuple-utils.mts +519 -0
- package/src/array/tuple-utils.test.mts +518 -0
- package/src/collections/imap-mapped.mts +801 -0
- package/src/collections/imap-mapped.test.mts +860 -0
- package/src/collections/imap.mts +651 -0
- package/src/collections/imap.test.mts +932 -0
- package/src/collections/index.mts +6 -0
- package/src/collections/iset-mapped.mts +889 -0
- package/src/collections/iset-mapped.test.mts +1187 -0
- package/src/collections/iset.mts +682 -0
- package/src/collections/iset.test.mts +1084 -0
- package/src/collections/queue.mts +390 -0
- package/src/collections/queue.test.mts +282 -0
- package/src/collections/stack.mts +423 -0
- package/src/collections/stack.test.mts +225 -0
- package/src/expect-type.mts +206 -0
- package/src/functional/index.mts +4 -0
- package/src/functional/match.mts +300 -0
- package/src/functional/match.test.mts +177 -0
- package/src/functional/optional.mts +733 -0
- package/src/functional/optional.test.mts +619 -0
- package/src/functional/pipe.mts +212 -0
- package/src/functional/pipe.test.mts +85 -0
- package/src/functional/result.mts +1134 -0
- package/src/functional/result.test.mts +777 -0
- package/src/globals.d.mts +38 -0
- package/src/guard/has-key.mts +119 -0
- package/src/guard/has-key.test.mts +219 -0
- package/src/guard/index.mts +7 -0
- package/src/guard/is-non-empty-string.mts +108 -0
- package/src/guard/is-non-empty-string.test.mts +91 -0
- package/src/guard/is-non-null-object.mts +106 -0
- package/src/guard/is-non-null-object.test.mts +90 -0
- package/src/guard/is-primitive.mts +165 -0
- package/src/guard/is-primitive.test.mts +102 -0
- package/src/guard/is-record.mts +153 -0
- package/src/guard/is-record.test.mts +112 -0
- package/src/guard/is-type.mts +450 -0
- package/src/guard/is-type.test.mts +496 -0
- package/src/guard/key-is-in.mts +163 -0
- package/src/guard/key-is-in.test.mts +19 -0
- package/src/index.mts +10 -0
- package/src/iterator/index.mts +1 -0
- package/src/iterator/range.mts +120 -0
- package/src/iterator/range.test.mts +33 -0
- package/src/json/index.mts +1 -0
- package/src/json/json.mts +711 -0
- package/src/json/json.test.mts +628 -0
- package/src/number/branded-types/finite-number.mts +354 -0
- package/src/number/branded-types/finite-number.test.mts +135 -0
- package/src/number/branded-types/index.mts +26 -0
- package/src/number/branded-types/int.mts +278 -0
- package/src/number/branded-types/int.test.mts +140 -0
- package/src/number/branded-types/int16.mts +192 -0
- package/src/number/branded-types/int16.test.mts +170 -0
- package/src/number/branded-types/int32.mts +193 -0
- package/src/number/branded-types/int32.test.mts +170 -0
- package/src/number/branded-types/non-negative-finite-number.mts +223 -0
- package/src/number/branded-types/non-negative-finite-number.test.mts +188 -0
- package/src/number/branded-types/non-negative-int16.mts +187 -0
- package/src/number/branded-types/non-negative-int16.test.mts +201 -0
- package/src/number/branded-types/non-negative-int32.mts +187 -0
- package/src/number/branded-types/non-negative-int32.test.mts +204 -0
- package/src/number/branded-types/non-zero-finite-number.mts +229 -0
- package/src/number/branded-types/non-zero-finite-number.test.mts +198 -0
- package/src/number/branded-types/non-zero-int.mts +167 -0
- package/src/number/branded-types/non-zero-int.test.mts +177 -0
- package/src/number/branded-types/non-zero-int16.mts +196 -0
- package/src/number/branded-types/non-zero-int16.test.mts +195 -0
- package/src/number/branded-types/non-zero-int32.mts +196 -0
- package/src/number/branded-types/non-zero-int32.test.mts +197 -0
- package/src/number/branded-types/non-zero-safe-int.mts +196 -0
- package/src/number/branded-types/non-zero-safe-int.test.mts +232 -0
- package/src/number/branded-types/non-zero-uint16.mts +189 -0
- package/src/number/branded-types/non-zero-uint16.test.mts +199 -0
- package/src/number/branded-types/non-zero-uint32.mts +189 -0
- package/src/number/branded-types/non-zero-uint32.test.mts +199 -0
- package/src/number/branded-types/positive-finite-number.mts +241 -0
- package/src/number/branded-types/positive-finite-number.test.mts +204 -0
- package/src/number/branded-types/positive-int.mts +304 -0
- package/src/number/branded-types/positive-int.test.mts +176 -0
- package/src/number/branded-types/positive-int16.mts +188 -0
- package/src/number/branded-types/positive-int16.test.mts +197 -0
- package/src/number/branded-types/positive-int32.mts +188 -0
- package/src/number/branded-types/positive-int32.test.mts +197 -0
- package/src/number/branded-types/positive-safe-int.mts +187 -0
- package/src/number/branded-types/positive-safe-int.test.mts +210 -0
- package/src/number/branded-types/positive-uint16.mts +188 -0
- package/src/number/branded-types/positive-uint16.test.mts +203 -0
- package/src/number/branded-types/positive-uint32.mts +188 -0
- package/src/number/branded-types/positive-uint32.test.mts +203 -0
- package/src/number/branded-types/safe-int.mts +291 -0
- package/src/number/branded-types/safe-int.test.mts +170 -0
- package/src/number/branded-types/safe-uint.mts +187 -0
- package/src/number/branded-types/safe-uint.test.mts +176 -0
- package/src/number/branded-types/uint.mts +179 -0
- package/src/number/branded-types/uint.test.mts +158 -0
- package/src/number/branded-types/uint16.mts +186 -0
- package/src/number/branded-types/uint16.test.mts +170 -0
- package/src/number/branded-types/uint32.mts +218 -0
- package/src/number/branded-types/uint32.test.mts +170 -0
- package/src/number/enum/index.mts +2 -0
- package/src/number/enum/int8.mts +344 -0
- package/src/number/enum/int8.test.mts +180 -0
- package/src/number/enum/uint8.mts +293 -0
- package/src/number/enum/uint8.test.mts +164 -0
- package/src/number/index.mts +4 -0
- package/src/number/num.mts +604 -0
- package/src/number/num.test.mts +242 -0
- package/src/number/refined-number-utils.mts +566 -0
- package/src/object/index.mts +1 -0
- package/src/object/object.mts +447 -0
- package/src/object/object.test.mts +124 -0
- package/src/others/cast-mutable.mts +113 -0
- package/src/others/cast-readonly.mts +192 -0
- package/src/others/cast-readonly.test.mts +89 -0
- package/src/others/if-then.mts +98 -0
- package/src/others/if-then.test.mts +75 -0
- package/src/others/index.mts +7 -0
- package/src/others/map-nullable.mts +172 -0
- package/src/others/map-nullable.test.mts +297 -0
- package/src/others/memoize-function.mts +196 -0
- package/src/others/memoize-function.test.mts +168 -0
- package/src/others/tuple.mts +160 -0
- package/src/others/tuple.test.mts +11 -0
- package/src/others/unknown-to-string.mts +215 -0
- package/src/others/unknown-to-string.test.mts +114 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { Optional } from './optional.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
* Utility type to merge intersection types into a single object type.
|
|
6
|
+
* This helps with TypeScript's display of complex intersection types.
|
|
7
|
+
* @template T The intersection type to merge.
|
|
8
|
+
*/
|
|
9
|
+
type MergeIntersection<T> = {
|
|
10
|
+
[K in keyof T]: T[K];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new pipe object that allows for chaining operations on a value.
|
|
15
|
+
*
|
|
16
|
+
* This function provides a fluent interface for applying transformations to values,
|
|
17
|
+
* with intelligent method selection based on the input type:
|
|
18
|
+
* - For `Optional` values: Provides `mapOptional` for safe Optional transformations
|
|
19
|
+
* - For other values: Provides `mapNullable` for null-safe transformations
|
|
20
|
+
* - All types get the basic `map` method for general transformations
|
|
21
|
+
*
|
|
22
|
+
* The pipe maintains type safety throughout the chain, automatically selecting
|
|
23
|
+
* the appropriate overload based on the current value type.
|
|
24
|
+
*
|
|
25
|
+
* @template A The type of the initial value to wrap in a pipe.
|
|
26
|
+
* @param a The initial value to wrap in a pipe.
|
|
27
|
+
* @returns A pipe object with chaining methods appropriate for the value type.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* Basic value transformation chaining:
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // Simple sequential transformations
|
|
33
|
+
* const result = pipe(10)
|
|
34
|
+
* .map(x => x * 2) // 20
|
|
35
|
+
* .map(x => x + 5) // 25
|
|
36
|
+
* .map(x => x.toString()) // '25'
|
|
37
|
+
* .value;
|
|
38
|
+
*
|
|
39
|
+
* // String processing pipeline
|
|
40
|
+
* const processed = pipe(" Hello World ")
|
|
41
|
+
* .map(s => s.trim()) // "Hello World"
|
|
42
|
+
* .map(s => s.toLowerCase()) // "hello world"
|
|
43
|
+
* .map(s => s.split(' ')) // ["hello", "world"]
|
|
44
|
+
* .map(arr => arr.join('-')) // "hello-world"
|
|
45
|
+
* .value;
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* Nullable value handling with automatic null checking:
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // Safe operations on potentially null values
|
|
52
|
+
* const maybeNumber: number | null = getNumberFromAPI();
|
|
53
|
+
* const result = pipe(maybeNumber)
|
|
54
|
+
* .mapNullable(x => x * 2) // Only applies if not null
|
|
55
|
+
* .mapNullable(x => `Result: ${x}`) // Only applies if previous step succeeded
|
|
56
|
+
* .value; // 'Result: 20' or undefined
|
|
57
|
+
*
|
|
58
|
+
* // Handling undefined values
|
|
59
|
+
* const maybeUser: User | undefined = findUser(id);
|
|
60
|
+
* const userName = pipe(maybeUser)
|
|
61
|
+
* .mapNullable(user => user.name)
|
|
62
|
+
* .mapNullable(name => name.toUpperCase())
|
|
63
|
+
* .value; // string or undefined
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* Optional value handling with monadic operations:
|
|
68
|
+
* ```typescript
|
|
69
|
+
* // Working with Optional types
|
|
70
|
+
* const optional = Optional.some(42);
|
|
71
|
+
* const result = pipe(optional)
|
|
72
|
+
* .mapOptional(x => x / 2) // Optional.some(21)
|
|
73
|
+
* .mapOptional(x => Math.sqrt(x)) // Optional.some(~4.58)
|
|
74
|
+
* .value; // Optional.some(4.58...)
|
|
75
|
+
*
|
|
76
|
+
* // Optional chains that can become None
|
|
77
|
+
* const parseAndProcess = (input: string) =>
|
|
78
|
+
* pipe(Optional.fromNullable(input))
|
|
79
|
+
* .mapOptional(s => s.trim())
|
|
80
|
+
* .mapOptional(s => s.length > 0 ? s : null) // Could become None
|
|
81
|
+
* .mapOptional(s => parseInt(s, 10))
|
|
82
|
+
* .mapOptional(n => isNaN(n) ? null : n)
|
|
83
|
+
* .value; // Optional<number>
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* Mixed type transformations:
|
|
88
|
+
* ```typescript
|
|
89
|
+
* // Starting with a string, transforming through different types
|
|
90
|
+
* const complex = pipe('hello')
|
|
91
|
+
* .map(s => s.length) // number: 5
|
|
92
|
+
* .map(n => n > 3 ? n : null) // number | null: 5
|
|
93
|
+
* .mapNullable(n => n * 10) // number: 50 (or undefined if null)
|
|
94
|
+
* .value; // 50 or undefined
|
|
95
|
+
*
|
|
96
|
+
* // API response processing
|
|
97
|
+
* const processApiResponse = (response: ApiResponse) =>
|
|
98
|
+
* pipe(response)
|
|
99
|
+
* .map(r => r.data) // Extract data
|
|
100
|
+
* .mapNullable(data => data.user) // Safe user access
|
|
101
|
+
* .mapNullable(user => user.profile) // Safe profile access
|
|
102
|
+
* .mapNullable(profile => profile.avatar) // Safe avatar access
|
|
103
|
+
* .value; // string | undefined
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* Error-safe computation chains:
|
|
108
|
+
* ```typescript
|
|
109
|
+
* // Building complex computations safely
|
|
110
|
+
* const safeCalculation = (input: unknown) =>
|
|
111
|
+
* pipe(input)
|
|
112
|
+
* .map(val => typeof val === 'number' ? val : null)
|
|
113
|
+
* .mapNullable(n => n > 0 ? n : null) // Positive numbers only
|
|
114
|
+
* .mapNullable(n => Math.sqrt(n)) // Safe square root
|
|
115
|
+
* .mapNullable(n => n < 100 ? n : null) // Limit result
|
|
116
|
+
* .mapNullable(n => Math.round(n * 100) / 100) // Round to 2 decimals
|
|
117
|
+
* .value; // number | undefined
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
121
|
+
export const pipe: PipeFnOverload = (<const A,>(a: A) => {
|
|
122
|
+
if (Optional.isOptional(a)) {
|
|
123
|
+
return {
|
|
124
|
+
value: a,
|
|
125
|
+
map: (fn) => pipe(fn(a)),
|
|
126
|
+
mapOptional: (fn) => pipe(Optional.map(a, fn)),
|
|
127
|
+
} satisfies PipeWithMapOptional<Optional.Base>;
|
|
128
|
+
} else {
|
|
129
|
+
return {
|
|
130
|
+
value: a,
|
|
131
|
+
map: (fn) => pipe(fn(a)),
|
|
132
|
+
mapNullable: (fn) => pipe(a == null ? undefined : fn(a)),
|
|
133
|
+
} satisfies PipeWithMapNullable<A>;
|
|
134
|
+
}
|
|
135
|
+
}) as PipeFnOverload;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @internal
|
|
139
|
+
* Overloaded function type for the pipe function.
|
|
140
|
+
* Automatically selects the appropriate pipe type based on input:
|
|
141
|
+
* - Optional types get PipeWithMapOptional
|
|
142
|
+
* - All other types get PipeWithMapNullable
|
|
143
|
+
* @template A The type of value being piped.
|
|
144
|
+
*/
|
|
145
|
+
type PipeFnOverload = {
|
|
146
|
+
/** Creates a pipe for Optional values with mapOptional support. */
|
|
147
|
+
<const A extends Optional.Base>(a: A): PipeWithMapOptional<A>;
|
|
148
|
+
/** Creates a pipe for any other value type with mapNullable support. */
|
|
149
|
+
<const A>(a: A): PipeWithMapNullable<A>;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @internal
|
|
154
|
+
* Base pipe interface providing core functionality.
|
|
155
|
+
* All pipe types extend this interface.
|
|
156
|
+
* @template A The type of the current value in the pipe.
|
|
157
|
+
*/
|
|
158
|
+
type PipeBase<A> = Readonly<{
|
|
159
|
+
/** The current value being piped. */
|
|
160
|
+
value: A;
|
|
161
|
+
/**
|
|
162
|
+
* Maps the current value to a new value using the provided function.
|
|
163
|
+
* @template B The type of the new value.
|
|
164
|
+
* @param fn Function to transform the current value.
|
|
165
|
+
* @returns A new pipe containing the transformed value.
|
|
166
|
+
*/
|
|
167
|
+
map: <B>(fn: (a: A) => B) => PipeBase<B>;
|
|
168
|
+
}>;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @internal
|
|
172
|
+
* Pipe interface for non-Optional values, providing null-safe mapping.
|
|
173
|
+
* Extends PipeBase with mapNullable functionality.
|
|
174
|
+
* @template A The type of the current value in the pipe.
|
|
175
|
+
*/
|
|
176
|
+
type PipeWithMapNullable<A> = MergeIntersection<
|
|
177
|
+
PipeBase<A> &
|
|
178
|
+
Readonly<{
|
|
179
|
+
/**
|
|
180
|
+
* Maps the current value only if it's not null or undefined.
|
|
181
|
+
* If the current value is null/undefined, the transformation is skipped
|
|
182
|
+
* and undefined is propagated through the pipe.
|
|
183
|
+
* @template B The type of the transformed value.
|
|
184
|
+
* @param fn Function to transform the non-null value.
|
|
185
|
+
* @returns A new pipe containing the transformed value or undefined.
|
|
186
|
+
*/
|
|
187
|
+
mapNullable: <B>(fn: (a: NonNullable<A>) => B) => PipeBase<B | undefined>;
|
|
188
|
+
}>
|
|
189
|
+
>;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @internal
|
|
193
|
+
* Pipe interface for Optional values, providing Optional-aware mapping.
|
|
194
|
+
* Extends PipeBase with mapOptional functionality for monadic operations.
|
|
195
|
+
* @template A The Optional type currently in the pipe.
|
|
196
|
+
*/
|
|
197
|
+
type PipeWithMapOptional<A extends Optional.Base> = MergeIntersection<
|
|
198
|
+
PipeBase<A> &
|
|
199
|
+
Readonly<{
|
|
200
|
+
/**
|
|
201
|
+
* Maps the value inside an Optional using Optional.map semantics.
|
|
202
|
+
* If the Optional is None, the transformation is skipped and None is propagated.
|
|
203
|
+
* If the Optional is Some, the transformation is applied to the inner value.
|
|
204
|
+
* @template B The type of the transformed inner value.
|
|
205
|
+
* @param fn Function to transform the inner value of the Optional.
|
|
206
|
+
* @returns A new pipe containing an Optional with the transformed value.
|
|
207
|
+
*/
|
|
208
|
+
mapOptional: <B>(
|
|
209
|
+
fn: (a: Optional.Unwrap<A>) => B,
|
|
210
|
+
) => PipeBase<Optional<B>>;
|
|
211
|
+
}>
|
|
212
|
+
>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { expectType } from '../expect-type.mjs';
|
|
2
|
+
import { Optional } from './optional.mjs';
|
|
3
|
+
import { pipe } from './pipe.mjs';
|
|
4
|
+
|
|
5
|
+
describe('pipe', () => {
|
|
6
|
+
test('basic pipe operations', () => {
|
|
7
|
+
const result = pipe(5)
|
|
8
|
+
.map((x) => x * 2)
|
|
9
|
+
.map((x) => x + 1).value;
|
|
10
|
+
|
|
11
|
+
expect(result).toBe(11);
|
|
12
|
+
expectType<typeof result, number>('=');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('pipe with string operations', () => {
|
|
16
|
+
const result = pipe('hello')
|
|
17
|
+
.map((s) => s.toUpperCase())
|
|
18
|
+
.map((s) => `${s}!`).value;
|
|
19
|
+
|
|
20
|
+
expect(result).toBe('HELLO!');
|
|
21
|
+
expectType<typeof result, string>('=');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('pipe with array operations', () => {
|
|
25
|
+
const result = pipe([1, 2, 3])
|
|
26
|
+
.map((arr) => arr.map((x) => x * 2))
|
|
27
|
+
.map((arr) => arr.length).value;
|
|
28
|
+
|
|
29
|
+
expect(result).toBe(3);
|
|
30
|
+
expectType<typeof result, number>('=');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('mapNullable with non-null value', () => {
|
|
34
|
+
const result = pipe(5 as number | null).mapNullable((x) => x * 2).value;
|
|
35
|
+
|
|
36
|
+
expect(result).toBe(10);
|
|
37
|
+
expectType<typeof result, number | undefined>('=');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('mapNullable with null value', () => {
|
|
41
|
+
const result = pipe(null as number | null).mapNullable((x) => x * 2).value;
|
|
42
|
+
|
|
43
|
+
expect(result).toBeUndefined();
|
|
44
|
+
expectType<typeof result, number | undefined>('=');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('mapNullable with undefined value', () => {
|
|
48
|
+
const result = pipe(undefined as number | undefined).mapNullable(
|
|
49
|
+
(x) => x * 2,
|
|
50
|
+
).value;
|
|
51
|
+
|
|
52
|
+
expect(result).toBeUndefined();
|
|
53
|
+
expectType<typeof result, number | undefined>('=');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('mapOptional with Some value', () => {
|
|
57
|
+
const optional = Optional.some(42);
|
|
58
|
+
const result = pipe(optional).mapOptional((x) => x * 2).value;
|
|
59
|
+
|
|
60
|
+
expect(Optional.isSome(result)).toBe(true);
|
|
61
|
+
if (Optional.isSome(result)) {
|
|
62
|
+
expect(result.value).toBe(84);
|
|
63
|
+
}
|
|
64
|
+
expectType<typeof result, Optional<number>>('=');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('mapOptional with None value', () => {
|
|
68
|
+
const optional: Optional<number> = Optional.none;
|
|
69
|
+
const result = pipe(optional).mapOptional((x) => x * 2).value;
|
|
70
|
+
|
|
71
|
+
expect(Optional.isNone(result)).toBe(true);
|
|
72
|
+
expectType<typeof result, Optional<number>>('=');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('chaining multiple operations', () => {
|
|
76
|
+
const result = pipe('5')
|
|
77
|
+
.map((s) => Number.parseInt(s, 10))
|
|
78
|
+
.map((n) => n * 3)
|
|
79
|
+
.map((n) => n.toString())
|
|
80
|
+
.map((s) => `${s} items`).value;
|
|
81
|
+
|
|
82
|
+
expect(result).toBe('15 items');
|
|
83
|
+
expectType<typeof result, string>('=');
|
|
84
|
+
});
|
|
85
|
+
});
|