ts-data-forge 6.0.0 → 6.1.1
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/dist/array/impl/array-utils-modification.d.mts.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts +28 -0
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.mjs +4 -1
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/index.mjs +1 -1
- package/dist/collections/imap.d.mts +1 -1
- package/dist/collections/iset-mapped.d.mts +1 -1
- package/dist/collections/iset.d.mts +1 -1
- package/dist/globals.d.mts +1 -2
- package/dist/guard/has-key.d.mts +1 -4
- package/dist/guard/has-key.d.mts.map +1 -1
- package/dist/object/object.d.mts.map +1 -1
- package/dist/object/object.mjs.map +1 -1
- package/package.json +53 -49
- package/src/array/impl/array-utils-modification.mts +19 -38
- package/src/array/impl/array-utils-overload-type-error.test.mts +4 -2
- package/src/array/impl/array-utils-reducing-value.mts +48 -0
- package/src/collections/imap.mts +1 -1
- package/src/collections/iset-mapped.mts +1 -1
- package/src/collections/iset.mts +1 -1
- package/src/functional/optional.test.mts +7 -5
- package/src/functional/result.test.mts +10 -8
- package/src/functional/ternary-result.test.mts +4 -4
- package/src/globals.d.mts +1 -2
- package/src/guard/has-key.mts +3 -6
- package/src/guard/has-key.test.mts +89 -186
- package/src/json/json.test.mts +5 -5
- package/src/number/branded-types/finite-number.test.mts +15 -11
- package/src/number/branded-types/int.test.mts +13 -13
- package/src/number/branded-types/int16.test.mts +15 -15
- package/src/number/branded-types/int32.test.mts +15 -15
- package/src/number/branded-types/non-negative-finite-number.test.mts +19 -15
- package/src/number/branded-types/non-negative-int16.test.mts +15 -15
- package/src/number/branded-types/non-negative-int32.test.mts +15 -15
- package/src/number/branded-types/non-zero-finite-number.test.mts +18 -18
- package/src/number/branded-types/non-zero-int.test.mts +18 -14
- package/src/number/branded-types/non-zero-int16.test.mts +19 -15
- package/src/number/branded-types/non-zero-int32.test.mts +19 -15
- package/src/number/branded-types/non-zero-safe-int.test.mts +22 -18
- package/src/number/branded-types/non-zero-uint16.test.mts +15 -15
- package/src/number/branded-types/non-zero-uint32.test.mts +15 -15
- package/src/number/branded-types/positive-finite-number.test.mts +18 -18
- package/src/number/branded-types/positive-int.test.mts +22 -16
- package/src/number/branded-types/positive-int16.test.mts +14 -14
- package/src/number/branded-types/positive-int32.test.mts +14 -14
- package/src/number/branded-types/positive-safe-int.test.mts +20 -18
- package/src/number/branded-types/positive-uint16.test.mts +15 -15
- package/src/number/branded-types/positive-uint32.test.mts +15 -15
- package/src/number/branded-types/safe-int.test.mts +21 -17
- package/src/number/branded-types/safe-uint.test.mts +22 -16
- package/src/number/branded-types/uint.test.mts +14 -14
- package/src/number/branded-types/uint16.test.mts +14 -14
- package/src/number/branded-types/uint32.test.mts +14 -14
- package/src/number/enum/int8.test.mts +1 -1
- package/src/number/enum/uint8.test.mts +1 -1
- package/src/object/object.mts +0 -1
- package/src/others/memoize-function.test.mts +1 -0
|
@@ -218,7 +218,7 @@ describe('Optional test', () => {
|
|
|
218
218
|
});
|
|
219
219
|
|
|
220
220
|
test('should throw for None', () => {
|
|
221
|
-
expect(() => Optional.unwrapThrow(Optional.none)).
|
|
221
|
+
expect(() => Optional.unwrapThrow(Optional.none)).toThrowError(
|
|
222
222
|
'`unwrapThrow()` has failed because it is `None`',
|
|
223
223
|
);
|
|
224
224
|
});
|
|
@@ -300,7 +300,9 @@ describe('Optional test', () => {
|
|
|
300
300
|
test('should throw with custom message for None', () => {
|
|
301
301
|
const expectNumber = Optional.expectToBe<number>('Expected a number');
|
|
302
302
|
|
|
303
|
-
expect(() => expectNumber(Optional.none)).
|
|
303
|
+
expect(() => expectNumber(Optional.none)).toThrowError(
|
|
304
|
+
'Expected a number',
|
|
305
|
+
);
|
|
304
306
|
});
|
|
305
307
|
|
|
306
308
|
test('should be curried', () => {
|
|
@@ -312,7 +314,7 @@ describe('Optional test', () => {
|
|
|
312
314
|
|
|
313
315
|
expect(expectValidId(id1)).toBe('user-123');
|
|
314
316
|
|
|
315
|
-
expect(() => expectValidId(id2)).
|
|
317
|
+
expect(() => expectValidId(id2)).toThrowError('ID is required');
|
|
316
318
|
});
|
|
317
319
|
|
|
318
320
|
test('should support curried form', () => {
|
|
@@ -326,7 +328,7 @@ describe('Optional test', () => {
|
|
|
326
328
|
|
|
327
329
|
const noneValue = Optional.none;
|
|
328
330
|
|
|
329
|
-
expect(() => getValue(noneValue)).
|
|
331
|
+
expect(() => getValue(noneValue)).toThrowError('Value must exist');
|
|
330
332
|
});
|
|
331
333
|
|
|
332
334
|
test('should work with pipe when curried', () => {
|
|
@@ -338,7 +340,7 @@ describe('Optional test', () => {
|
|
|
338
340
|
|
|
339
341
|
assert.deepStrictEqual(someResult, { name: 'Alice', age: 30 });
|
|
340
342
|
|
|
341
|
-
expect(() => pipe(Optional.none).map(expectUser).value).
|
|
343
|
+
expect(() => pipe(Optional.none).map(expectUser).value).toThrowError(
|
|
342
344
|
'User not found',
|
|
343
345
|
);
|
|
344
346
|
});
|
|
@@ -248,7 +248,7 @@ describe('Result test', () => {
|
|
|
248
248
|
test('throws on Err result', () => {
|
|
249
249
|
const result = Result.err('error message');
|
|
250
250
|
|
|
251
|
-
expect(() => Result.unwrapThrow(result)).
|
|
251
|
+
expect(() => Result.unwrapThrow(result)).toThrowError('error message');
|
|
252
252
|
});
|
|
253
253
|
});
|
|
254
254
|
|
|
@@ -589,7 +589,7 @@ describe('Result test', () => {
|
|
|
589
589
|
test('should throw for Ok', () => {
|
|
590
590
|
const result = Result.ok(42);
|
|
591
591
|
|
|
592
|
-
expect(() => Result.unwrapErrThrow(result)).
|
|
592
|
+
expect(() => Result.unwrapErrThrow(result)).toThrowError(
|
|
593
593
|
'Expected Err but got Ok: 42',
|
|
594
594
|
);
|
|
595
595
|
});
|
|
@@ -599,7 +599,7 @@ describe('Result test', () => {
|
|
|
599
599
|
|
|
600
600
|
expect(() =>
|
|
601
601
|
Result.unwrapErrThrow(result, (obj) => `Object(id=${obj.id})`),
|
|
602
|
-
).
|
|
602
|
+
).toThrowError('Expected Err but got Ok: Object(id=1)');
|
|
603
603
|
});
|
|
604
604
|
});
|
|
605
605
|
|
|
@@ -665,9 +665,9 @@ describe('Result test', () => {
|
|
|
665
665
|
test('should throw custom error for Err result', () => {
|
|
666
666
|
const result = Result.err('failed');
|
|
667
667
|
|
|
668
|
-
expect(() =>
|
|
669
|
-
'Operation must succeed',
|
|
670
|
-
);
|
|
668
|
+
expect(() =>
|
|
669
|
+
Result.expectToBe(result, 'Operation must succeed'),
|
|
670
|
+
).toThrowError('Operation must succeed');
|
|
671
671
|
});
|
|
672
672
|
|
|
673
673
|
test('should support curried form', () => {
|
|
@@ -681,7 +681,9 @@ describe('Result test', () => {
|
|
|
681
681
|
|
|
682
682
|
const errResult: Result<string, string> = Result.err('failed');
|
|
683
683
|
|
|
684
|
-
expect(() => mustBeOk(errResult)).
|
|
684
|
+
expect(() => mustBeOk(errResult)).toThrowError(
|
|
685
|
+
'Expected successful result',
|
|
686
|
+
);
|
|
685
687
|
});
|
|
686
688
|
|
|
687
689
|
test('should work with pipe when curried', () => {
|
|
@@ -693,7 +695,7 @@ describe('Result test', () => {
|
|
|
693
695
|
|
|
694
696
|
expect(
|
|
695
697
|
() => pipe(Result.err('validation error')).map(mustBeOk).value,
|
|
696
|
-
).
|
|
698
|
+
).toThrowError('Validation failed');
|
|
697
699
|
});
|
|
698
700
|
});
|
|
699
701
|
|
|
@@ -171,15 +171,15 @@ describe('TernaryResult test', () => {
|
|
|
171
171
|
test('throwing unwrap variants provide descriptive errors', () => {
|
|
172
172
|
expect(() =>
|
|
173
173
|
TernaryResult.unwrapThrow(TernaryResult.warn('notice', 'warned')),
|
|
174
|
-
).
|
|
174
|
+
).toThrowError(/Warn/u);
|
|
175
175
|
|
|
176
176
|
expect(() =>
|
|
177
177
|
TernaryResult.unwrapWarnThrow(TernaryResult.err('no warn')),
|
|
178
|
-
).
|
|
178
|
+
).toThrowError(/Err/u);
|
|
179
179
|
|
|
180
180
|
expect(() =>
|
|
181
181
|
TernaryResult.unwrapErrThrow(TernaryResult.ok('no err')),
|
|
182
|
-
).
|
|
182
|
+
).toThrowError(/Ok/u);
|
|
183
183
|
});
|
|
184
184
|
|
|
185
185
|
test('expectToBe unwraps Ok values', () => {
|
|
@@ -187,7 +187,7 @@ describe('TernaryResult test', () => {
|
|
|
187
187
|
|
|
188
188
|
expect(() =>
|
|
189
189
|
TernaryResult.expectToBe(TernaryResult.err('x'), 'missing'),
|
|
190
|
-
).
|
|
190
|
+
).toThrowError(/missing/u);
|
|
191
191
|
});
|
|
192
192
|
|
|
193
193
|
test('zip prefers Err over Warn or Ok.', () => {
|
package/src/globals.d.mts
CHANGED
|
@@ -13,8 +13,7 @@ type ArgArrayIndex<Ar extends readonly unknown[]> =
|
|
|
13
13
|
|
|
14
14
|
type ArgArrayIndexWithNegative<Ar extends readonly unknown[]> =
|
|
15
15
|
IsFixedLengthList<Ar> extends true
|
|
16
|
-
?
|
|
17
|
-
IndexOfTuple<[...Ar, 0]> | NegativeIndexOfTuple<Ar>
|
|
16
|
+
? IndexOfTuple<[...Ar, 0]> | NegativeIndexOfTuple<Ar>
|
|
18
17
|
: SizeType.ArgArrWithNegative;
|
|
19
18
|
|
|
20
19
|
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/length
|
package/src/guard/has-key.mts
CHANGED
|
@@ -58,14 +58,11 @@ export type HasKeyReturnType<
|
|
|
58
58
|
> = R extends R // union distribution
|
|
59
59
|
? K extends keyof R
|
|
60
60
|
? string extends keyof R
|
|
61
|
-
?
|
|
62
|
-
ReadonlyRecord<K, R[keyof R]> & R
|
|
61
|
+
? ReadonlyRecord<K, R[keyof R]> & R
|
|
63
62
|
: number extends keyof R
|
|
64
|
-
?
|
|
65
|
-
ReadonlyRecord<K, R[keyof R]> & R
|
|
63
|
+
? ReadonlyRecord<K, R[keyof R]> & R
|
|
66
64
|
: symbol extends keyof R
|
|
67
|
-
?
|
|
68
|
-
ReadonlyRecord<K, R[keyof R]> & R
|
|
65
|
+
? ReadonlyRecord<K, R[keyof R]> & R
|
|
69
66
|
: R
|
|
70
67
|
: never // omit union member that does not have key K
|
|
71
68
|
: never; // dummy case for union distribution
|
|
@@ -1,223 +1,126 @@
|
|
|
1
1
|
import { expectType } from '../expect-type.mjs';
|
|
2
2
|
import { hasKey, type HasKeyReturnType } from './has-key.mjs';
|
|
3
3
|
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
expectType<
|
|
11
|
-
HasKeyReturnType<Readonly<{ a: 0 }> | Readonly<{ b: 1 }>, 'b'>,
|
|
12
|
-
Readonly<{ b: 1 }>
|
|
13
|
-
>('=');
|
|
14
|
-
|
|
15
|
-
expectType<
|
|
16
|
-
HasKeyReturnType<Readonly<{ a: 0 }> | Readonly<{ b: 1 }>, 'd'>,
|
|
17
|
-
never
|
|
18
|
-
>('=');
|
|
19
|
-
|
|
20
|
-
expectType<
|
|
21
|
-
HasKeyReturnType<
|
|
22
|
-
| Readonly<{ a: 0 }>
|
|
23
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
24
|
-
| Readonly<{ b: 2 }>
|
|
25
|
-
| Readonly<{ c: 3 }>,
|
|
26
|
-
'a'
|
|
27
|
-
>,
|
|
28
|
-
Readonly<{ a: 0 }> | Readonly<{ a: 1; b: 1 }>
|
|
29
|
-
>('=');
|
|
30
|
-
|
|
31
|
-
expectType<
|
|
32
|
-
HasKeyReturnType<
|
|
33
|
-
| Readonly<{ a: 0 }>
|
|
34
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
35
|
-
| Readonly<{ b: 2 }>
|
|
36
|
-
| Readonly<{ c: 3 }>,
|
|
37
|
-
'b'
|
|
38
|
-
>,
|
|
39
|
-
Readonly<{ a: 1; b: 1 }> | Readonly<{ b: 2 }>
|
|
40
|
-
>('=');
|
|
41
|
-
|
|
42
|
-
expectType<
|
|
43
|
-
HasKeyReturnType<
|
|
44
|
-
| ReadonlyRecord<string, number>
|
|
45
|
-
| Readonly<{ a: 0 }>
|
|
46
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
47
|
-
| Readonly<{ b: 2 }>,
|
|
48
|
-
'a'
|
|
49
|
-
>,
|
|
50
|
-
| Readonly<{ a: 0 }>
|
|
51
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
52
|
-
| (ReadonlyRecord<'a', number> & ReadonlyRecord<string, number>)
|
|
53
|
-
>('=');
|
|
54
|
-
|
|
55
|
-
expectType<
|
|
56
|
-
HasKeyReturnType<ReadonlyRecord<string, unknown>, 'a'>,
|
|
57
|
-
ReadonlyRecord<'a', unknown> & ReadonlyRecord<string, unknown>
|
|
58
|
-
>('=');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
type R = Readonly<{ a: 0 }> | Readonly<{ b: 1 }>;
|
|
63
|
-
|
|
64
|
-
const obj: R = { a: 0 } as R;
|
|
65
|
-
|
|
66
|
-
if (hasKey(obj, 'a')) {
|
|
67
|
-
expectType<typeof obj.a, 0>('=');
|
|
68
|
-
|
|
69
|
-
expectType<typeof obj, Readonly<{ a: 0 }>>('=');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (hasKey(obj, 'c')) {
|
|
73
|
-
expectType<typeof obj, never>('=');
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
{
|
|
78
|
-
type R =
|
|
79
|
-
| Readonly<{ a: 0 }>
|
|
80
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
81
|
-
| Readonly<{ b: 2 }>
|
|
82
|
-
| Readonly<{ c: 3 }>;
|
|
83
|
-
|
|
84
|
-
const obj: R = { a: 0 } as R;
|
|
85
|
-
|
|
86
|
-
if (hasKey(obj, 'a') && hasKey(obj, 'b')) {
|
|
87
|
-
expectType<typeof obj.a, 1>('=');
|
|
88
|
-
|
|
89
|
-
expectType<typeof obj.b, 1>('=');
|
|
90
|
-
|
|
91
|
-
expectType<typeof obj, Readonly<{ a: 1; b: 1 }>>('=');
|
|
92
|
-
}
|
|
93
|
-
}
|
|
4
|
+
test('hasKey type inferences', () => {
|
|
5
|
+
{
|
|
6
|
+
expectType<
|
|
7
|
+
HasKeyReturnType<Readonly<{ a: 0 }> | Readonly<{ b: 1 }>, 'a'>,
|
|
8
|
+
Readonly<{ a: 0 }>
|
|
9
|
+
>('=');
|
|
94
10
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
100
|
-
| Readonly<{ b: 2 }>;
|
|
11
|
+
expectType<
|
|
12
|
+
HasKeyReturnType<Readonly<{ a: 0 }> | Readonly<{ b: 1 }>, 'b'>,
|
|
13
|
+
Readonly<{ b: 1 }>
|
|
14
|
+
>('=');
|
|
101
15
|
|
|
102
|
-
|
|
16
|
+
expectType<
|
|
17
|
+
HasKeyReturnType<Readonly<{ a: 0 }> | Readonly<{ b: 1 }>, 'd'>,
|
|
18
|
+
never
|
|
19
|
+
>('=');
|
|
103
20
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
21
|
+
expectType<
|
|
22
|
+
HasKeyReturnType<
|
|
23
|
+
| Readonly<{ a: 0 }>
|
|
24
|
+
| Readonly<{ a: 1; b: 1 }>
|
|
25
|
+
| Readonly<{ b: 2 }>
|
|
26
|
+
| Readonly<{ c: 3 }>,
|
|
27
|
+
'a'
|
|
28
|
+
>,
|
|
29
|
+
Readonly<{ a: 0 }> | Readonly<{ a: 1; b: 1 }>
|
|
30
|
+
>('=');
|
|
111
31
|
|
|
112
|
-
|
|
113
|
-
|
|
32
|
+
expectType<
|
|
33
|
+
HasKeyReturnType<
|
|
34
|
+
| Readonly<{ a: 0 }>
|
|
35
|
+
| Readonly<{ a: 1; b: 1 }>
|
|
36
|
+
| Readonly<{ b: 2 }>
|
|
37
|
+
| Readonly<{ c: 3 }>,
|
|
38
|
+
'b'
|
|
39
|
+
>,
|
|
40
|
+
Readonly<{ a: 1; b: 1 }> | Readonly<{ b: 2 }>
|
|
41
|
+
>('=');
|
|
114
42
|
|
|
115
43
|
expectType<
|
|
116
|
-
|
|
44
|
+
HasKeyReturnType<
|
|
45
|
+
| ReadonlyRecord<string, number>
|
|
46
|
+
| Readonly<{ a: 0 }>
|
|
47
|
+
| Readonly<{ a: 1; b: 1 }>
|
|
48
|
+
| Readonly<{ b: 2 }>,
|
|
49
|
+
'a'
|
|
50
|
+
>,
|
|
117
51
|
| Readonly<{ a: 0 }>
|
|
118
52
|
| Readonly<{ a: 1; b: 1 }>
|
|
119
53
|
| (ReadonlyRecord<'a', number> & ReadonlyRecord<string, number>)
|
|
120
54
|
>('=');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (hasKey(obj, 'a') && hasKey(obj, 'b')) {
|
|
124
|
-
expectType<typeof obj.a, number>('=');
|
|
125
|
-
|
|
126
|
-
expectType<typeof obj.b, number>('=');
|
|
127
55
|
|
|
128
56
|
expectType<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
| (ReadonlyRecord<'a', number> &
|
|
132
|
-
ReadonlyRecord<'b', number> &
|
|
133
|
-
ReadonlyRecord<string, number>)
|
|
57
|
+
HasKeyReturnType<ReadonlyRecord<string, unknown>, 'a'>,
|
|
58
|
+
ReadonlyRecord<'a', unknown> & ReadonlyRecord<string, unknown>
|
|
134
59
|
>('=');
|
|
135
60
|
}
|
|
136
|
-
}
|
|
137
61
|
|
|
138
|
-
{
|
|
139
|
-
|
|
62
|
+
{
|
|
63
|
+
type R = Readonly<{ a: 0 }> | Readonly<{ b: 1 }>;
|
|
140
64
|
|
|
141
|
-
|
|
142
|
-
expectType<typeof o.a, unknown>('=');
|
|
65
|
+
const obj: R = { a: 0 } as R;
|
|
143
66
|
|
|
144
|
-
|
|
145
|
-
typeof
|
|
146
|
-
ReadonlyRecord<'a', unknown> & ReadonlyRecord<string, unknown>
|
|
147
|
-
>('=');
|
|
148
|
-
}
|
|
67
|
+
if (hasKey(obj, 'a')) {
|
|
68
|
+
expectType<typeof obj.a, 0>('=');
|
|
149
69
|
|
|
150
|
-
|
|
151
|
-
|
|
70
|
+
expectType<typeof obj, Readonly<{ a: 0 }>>('=');
|
|
71
|
+
}
|
|
152
72
|
|
|
153
|
-
|
|
154
|
-
typeof
|
|
155
|
-
|
|
156
|
-
>('=');
|
|
73
|
+
if (hasKey(obj, 'c')) {
|
|
74
|
+
expectType<typeof obj, never>('=');
|
|
75
|
+
}
|
|
157
76
|
}
|
|
158
77
|
|
|
159
|
-
|
|
160
|
-
|
|
78
|
+
{
|
|
79
|
+
type R =
|
|
80
|
+
| Readonly<{ a: 0 }>
|
|
81
|
+
| Readonly<{ a: 1; b: 1 }>
|
|
82
|
+
| Readonly<{ b: 2 }>
|
|
83
|
+
| Readonly<{ c: 3 }>;
|
|
161
84
|
|
|
162
|
-
|
|
85
|
+
const obj: R = { a: 0 } as R;
|
|
163
86
|
|
|
164
|
-
|
|
165
|
-
typeof
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
87
|
+
if (hasKey(obj, 'a') && hasKey(obj, 'b')) {
|
|
88
|
+
expectType<typeof obj.a, 1>('=');
|
|
89
|
+
|
|
90
|
+
expectType<typeof obj.b, 1>('=');
|
|
91
|
+
|
|
92
|
+
expectType<typeof obj, Readonly<{ a: 1; b: 1 }>>('=');
|
|
93
|
+
}
|
|
170
94
|
}
|
|
171
95
|
|
|
172
96
|
{
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
* which doesn't work well.
|
|
179
|
-
*/
|
|
180
|
-
|
|
181
|
-
const hasOwnNaive = <R extends UnknownRecord, K extends string>(
|
|
182
|
-
obj: R,
|
|
183
|
-
key: K,
|
|
184
|
-
): obj is R & Record<K, R[K]> => hasKey(obj, key);
|
|
185
|
-
|
|
186
|
-
{
|
|
187
|
-
type O =
|
|
188
|
-
| Readonly<{ a: 0 }>
|
|
189
|
-
| Readonly<{ a: 1; b: 1 }>
|
|
190
|
-
| Readonly<{ b: 2 }>
|
|
191
|
-
| Record<string, number>;
|
|
97
|
+
type R =
|
|
98
|
+
| ReadonlyRecord<string, number>
|
|
99
|
+
| Readonly<{ a: 0 }>
|
|
100
|
+
| Readonly<{ a: 1; b: 1 }>
|
|
101
|
+
| Readonly<{ b: 2 }>;
|
|
192
102
|
|
|
193
|
-
|
|
103
|
+
const obj: R = { a: 0 } as R;
|
|
194
104
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
105
|
+
expectType<
|
|
106
|
+
R,
|
|
107
|
+
| ReadonlyRecord<string, number>
|
|
108
|
+
| Readonly<{ a: 0 }>
|
|
109
|
+
| Readonly<{ a: 1; b: 1 }>
|
|
110
|
+
| Readonly<{ b: 2 }>
|
|
111
|
+
>('=');
|
|
198
112
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
expectType<typeof o2.a, number>('=');
|
|
202
|
-
}
|
|
203
|
-
}
|
|
113
|
+
if (hasKey(obj, 'a')) {
|
|
114
|
+
expectType<typeof obj.a, number>('=');
|
|
204
115
|
|
|
205
|
-
|
|
206
|
-
|
|
116
|
+
expectType<
|
|
117
|
+
typeof obj,
|
|
207
118
|
| Readonly<{ a: 0 }>
|
|
208
119
|
| Readonly<{ a: 1; b: 1 }>
|
|
209
|
-
|
|
|
210
|
-
|
|
211
|
-
const o2 = { b: 2 } as O;
|
|
212
|
-
|
|
213
|
-
if (hasOwnNaive(o2, 'a')) {
|
|
214
|
-
expectType<typeof o2.a, unknown>('=');
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
218
|
-
if ('a' in o2) {
|
|
219
|
-
expectType<typeof o2.a, 0 | 1>('=');
|
|
220
|
-
}
|
|
120
|
+
| (ReadonlyRecord<'a', number> & ReadonlyRecord<string, number>)
|
|
121
|
+
>('=');
|
|
221
122
|
}
|
|
222
123
|
}
|
|
223
|
-
|
|
124
|
+
|
|
125
|
+
assert.strictEqual(true, true);
|
|
126
|
+
});
|
package/src/json/json.test.mts
CHANGED
|
@@ -118,11 +118,11 @@ describe('parse', () => {
|
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
test('should not throw errors', () => {
|
|
121
|
-
expect(() => Json.parse('{{{')).not.
|
|
121
|
+
expect(() => Json.parse('{{{')).not.toThrowError();
|
|
122
122
|
|
|
123
|
-
expect(() => Json.parse('null null')).not.
|
|
123
|
+
expect(() => Json.parse('null null')).not.toThrowError();
|
|
124
124
|
|
|
125
|
-
expect(() => Json.parse(String(undefined))).not.
|
|
125
|
+
expect(() => Json.parse(String(undefined))).not.toThrowError();
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
test('should use reviver function to transform values', () => {
|
|
@@ -323,9 +323,9 @@ describe('stringify', () => {
|
|
|
323
323
|
|
|
324
324
|
mut_circularArray.push(mut_circularArray);
|
|
325
325
|
|
|
326
|
-
expect(() => Json.stringify(mut_circularArray)).not.
|
|
326
|
+
expect(() => Json.stringify(mut_circularArray)).not.toThrowError();
|
|
327
327
|
|
|
328
|
-
expect(() => Json.stringify({ fn: () => {} })).not.
|
|
328
|
+
expect(() => Json.stringify({ fn: () => {} })).not.toThrowError();
|
|
329
329
|
});
|
|
330
330
|
|
|
331
331
|
test('should use replacer function to filter values', () => {
|
|
@@ -6,27 +6,31 @@ import { asNonZeroFiniteNumber } from './non-zero-finite-number.mjs';
|
|
|
6
6
|
describe('FiniteNumber test', () => {
|
|
7
7
|
describe(asFiniteNumber, () => {
|
|
8
8
|
test('accepts valid finite numbers', () => {
|
|
9
|
-
expect(() => asFiniteNumber(0)).not.
|
|
9
|
+
expect(() => asFiniteNumber(0)).not.toThrowError();
|
|
10
10
|
|
|
11
|
-
expect(() => asFiniteNumber(1)).not.
|
|
11
|
+
expect(() => asFiniteNumber(1)).not.toThrowError();
|
|
12
12
|
|
|
13
|
-
expect(() => asFiniteNumber(-1)).not.
|
|
13
|
+
expect(() => asFiniteNumber(-1)).not.toThrowError();
|
|
14
14
|
|
|
15
|
-
expect(() => asFiniteNumber(3.14)).not.
|
|
15
|
+
expect(() => asFiniteNumber(3.14)).not.toThrowError();
|
|
16
16
|
|
|
17
|
-
expect(() => asFiniteNumber(-2.5)).not.
|
|
17
|
+
expect(() => asFiniteNumber(-2.5)).not.toThrowError();
|
|
18
18
|
|
|
19
|
-
expect(() => asFiniteNumber(Number.MAX_VALUE)).not.
|
|
19
|
+
expect(() => asFiniteNumber(Number.MAX_VALUE)).not.toThrowError();
|
|
20
20
|
|
|
21
|
-
expect(() => asFiniteNumber(-Number.MAX_VALUE)).not.
|
|
21
|
+
expect(() => asFiniteNumber(-Number.MAX_VALUE)).not.toThrowError();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
test('rejects non-finite numbers', () => {
|
|
25
|
-
expect(() => asFiniteNumber(Number.NaN)).
|
|
25
|
+
expect(() => asFiniteNumber(Number.NaN)).toThrowError(TypeError);
|
|
26
26
|
|
|
27
|
-
expect(() => asFiniteNumber(Number.POSITIVE_INFINITY)).
|
|
27
|
+
expect(() => asFiniteNumber(Number.POSITIVE_INFINITY)).toThrowError(
|
|
28
|
+
TypeError,
|
|
29
|
+
);
|
|
28
30
|
|
|
29
|
-
expect(() => asFiniteNumber(Number.NEGATIVE_INFINITY)).
|
|
31
|
+
expect(() => asFiniteNumber(Number.NEGATIVE_INFINITY)).toThrowError(
|
|
32
|
+
TypeError,
|
|
33
|
+
);
|
|
30
34
|
});
|
|
31
35
|
|
|
32
36
|
test('returns the same value for valid inputs', () => {
|
|
@@ -44,7 +48,7 @@ describe('FiniteNumber test', () => {
|
|
|
44
48
|
] as const)(
|
|
45
49
|
`asFiniteNumber($name) should throw a TypeError`,
|
|
46
50
|
({ value }) => {
|
|
47
|
-
expect(() => asFiniteNumber(value)).
|
|
51
|
+
expect(() => asFiniteNumber(value)).toThrowError(
|
|
48
52
|
new TypeError(`Expected a finite number, got: ${value}`),
|
|
49
53
|
);
|
|
50
54
|
},
|
|
@@ -6,31 +6,31 @@ import { asNonZeroInt } from './non-zero-int.mjs';
|
|
|
6
6
|
describe('Int test', () => {
|
|
7
7
|
describe(asInt, () => {
|
|
8
8
|
test('accepts valid integers', () => {
|
|
9
|
-
expect(() => asInt(0)).not.
|
|
9
|
+
expect(() => asInt(0)).not.toThrowError();
|
|
10
10
|
|
|
11
|
-
expect(() => asInt(1)).not.
|
|
11
|
+
expect(() => asInt(1)).not.toThrowError();
|
|
12
12
|
|
|
13
|
-
expect(() => asInt(-1)).not.
|
|
13
|
+
expect(() => asInt(-1)).not.toThrowError();
|
|
14
14
|
|
|
15
|
-
expect(() => asInt(42)).not.
|
|
15
|
+
expect(() => asInt(42)).not.toThrowError();
|
|
16
16
|
|
|
17
|
-
expect(() => asInt(-42)).not.
|
|
17
|
+
expect(() => asInt(-42)).not.toThrowError();
|
|
18
18
|
|
|
19
|
-
expect(() => asInt(Number.MAX_SAFE_INTEGER)).not.
|
|
19
|
+
expect(() => asInt(Number.MAX_SAFE_INTEGER)).not.toThrowError();
|
|
20
20
|
|
|
21
|
-
expect(() => asInt(Number.MIN_SAFE_INTEGER)).not.
|
|
21
|
+
expect(() => asInt(Number.MIN_SAFE_INTEGER)).not.toThrowError();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
test('rejects non-integers', () => {
|
|
25
|
-
expect(() => asInt(Number.NaN)).
|
|
25
|
+
expect(() => asInt(Number.NaN)).toThrowError(TypeError);
|
|
26
26
|
|
|
27
|
-
expect(() => asInt(Number.POSITIVE_INFINITY)).
|
|
27
|
+
expect(() => asInt(Number.POSITIVE_INFINITY)).toThrowError(TypeError);
|
|
28
28
|
|
|
29
|
-
expect(() => asInt(Number.NEGATIVE_INFINITY)).
|
|
29
|
+
expect(() => asInt(Number.NEGATIVE_INFINITY)).toThrowError(TypeError);
|
|
30
30
|
|
|
31
|
-
expect(() => asInt(1.2)).
|
|
31
|
+
expect(() => asInt(1.2)).toThrowError(TypeError);
|
|
32
32
|
|
|
33
|
-
expect(() => asInt(-3.4)).
|
|
33
|
+
expect(() => asInt(-3.4)).toThrowError(TypeError);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
test('returns the same value for valid inputs', () => {
|
|
@@ -48,7 +48,7 @@ describe('Int test', () => {
|
|
|
48
48
|
{ name: '1.2', value: 1.2 },
|
|
49
49
|
{ name: '-3.4', value: -3.4 },
|
|
50
50
|
] as const)(`asInt($name) should throw a TypeError`, ({ value }) => {
|
|
51
|
-
expect(() => asInt(value)).
|
|
51
|
+
expect(() => asInt(value)).toThrowError(
|
|
52
52
|
new TypeError(`Expected an integer, got: ${value}`),
|
|
53
53
|
);
|
|
54
54
|
});
|
|
@@ -6,37 +6,37 @@ import { asNonZeroInt16 } from './non-zero-int16.mjs';
|
|
|
6
6
|
describe('Int16 test', () => {
|
|
7
7
|
describe(asInt16, () => {
|
|
8
8
|
test('accepts valid int16 values', () => {
|
|
9
|
-
expect(() => asInt16(0)).not.
|
|
9
|
+
expect(() => asInt16(0)).not.toThrowError();
|
|
10
10
|
|
|
11
|
-
expect(() => asInt16(1)).not.
|
|
11
|
+
expect(() => asInt16(1)).not.toThrowError();
|
|
12
12
|
|
|
13
|
-
expect(() => asInt16(-1)).not.
|
|
13
|
+
expect(() => asInt16(-1)).not.toThrowError();
|
|
14
14
|
|
|
15
|
-
expect(() => asInt16(32_767)).not.
|
|
15
|
+
expect(() => asInt16(32_767)).not.toThrowError(); // 2^15 - 1
|
|
16
16
|
|
|
17
|
-
expect(() => asInt16(-32_768)).not.
|
|
17
|
+
expect(() => asInt16(-32_768)).not.toThrowError(); // -2^15
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
test('rejects values outside int16 range', () => {
|
|
21
|
-
expect(() => asInt16(32_768)).
|
|
21
|
+
expect(() => asInt16(32_768)).toThrowError(TypeError); // 2^15
|
|
22
22
|
|
|
23
|
-
expect(() => asInt16(-32_769)).
|
|
23
|
+
expect(() => asInt16(-32_769)).toThrowError(TypeError); // -2^15 - 1
|
|
24
24
|
|
|
25
|
-
expect(() => asInt16(65_536)).
|
|
25
|
+
expect(() => asInt16(65_536)).toThrowError(TypeError);
|
|
26
26
|
|
|
27
|
-
expect(() => asInt16(-65_536)).
|
|
27
|
+
expect(() => asInt16(-65_536)).toThrowError(TypeError);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
test('rejects non-integers', () => {
|
|
31
|
-
expect(() => asInt16(Number.NaN)).
|
|
31
|
+
expect(() => asInt16(Number.NaN)).toThrowError(TypeError);
|
|
32
32
|
|
|
33
|
-
expect(() => asInt16(Number.POSITIVE_INFINITY)).
|
|
33
|
+
expect(() => asInt16(Number.POSITIVE_INFINITY)).toThrowError(TypeError);
|
|
34
34
|
|
|
35
|
-
expect(() => asInt16(Number.NEGATIVE_INFINITY)).
|
|
35
|
+
expect(() => asInt16(Number.NEGATIVE_INFINITY)).toThrowError(TypeError);
|
|
36
36
|
|
|
37
|
-
expect(() => asInt16(1.2)).
|
|
37
|
+
expect(() => asInt16(1.2)).toThrowError(TypeError);
|
|
38
38
|
|
|
39
|
-
expect(() => asInt16(-3.4)).
|
|
39
|
+
expect(() => asInt16(-3.4)).toThrowError(TypeError);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
test('returns the same value for valid inputs', () => {
|
|
@@ -58,7 +58,7 @@ describe('Int16 test', () => {
|
|
|
58
58
|
{ name: '1.2', value: 1.2 },
|
|
59
59
|
{ name: '-3.4', value: -3.4 },
|
|
60
60
|
] as const)(`asInt16($name) should throw a TypeError`, ({ value }) => {
|
|
61
|
-
expect(() => asInt16(value)).
|
|
61
|
+
expect(() => asInt16(value)).toThrowError(
|
|
62
62
|
new TypeError(`Expected an integer in [-2^15, 2^15), got: ${value}`),
|
|
63
63
|
);
|
|
64
64
|
});
|