ts-data-forge 6.3.1 → 6.5.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/README.md +5 -3
- package/dist/array/impl/array-utils-element-access.d.mts +5 -5
- package/dist/array/impl/array-utils-element-access.mjs +4 -4
- package/dist/array/impl/array-utils-iterators.d.mts +1 -1
- package/dist/array/impl/array-utils-iterators.mjs +1 -1
- package/dist/array/impl/array-utils-modification.d.mts +4 -4
- package/dist/array/impl/array-utils-reducing-value.d.mts +5 -5
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.mjs +1 -0
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/array-utils-search.d.mts +8 -8
- package/dist/array/impl/array-utils-set-op.d.mts.map +1 -1
- package/dist/array/impl/array-utils-set-op.mjs +3 -1
- package/dist/array/impl/array-utils-set-op.mjs.map +1 -1
- package/dist/array/impl/array-utils-size.d.mts +1 -1
- package/dist/array/impl/array-utils-size.mjs +1 -1
- package/dist/array/impl/array-utils-slice-clamped.d.mts +1 -1
- package/dist/array/impl/array-utils-slicing.d.mts +3 -3
- package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-validation.d.mts +7 -7
- package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-validation.mjs +22 -12
- package/dist/array/impl/array-utils-validation.mjs.map +1 -1
- package/dist/collections/imap.d.mts +19 -16
- package/dist/collections/imap.d.mts.map +1 -1
- package/dist/collections/imap.mjs +1 -1
- package/dist/collections/imap.mjs.map +1 -1
- package/dist/collections/iset-mapped.d.mts +2 -2
- package/dist/collections/iset-mapped.d.mts.map +1 -1
- package/dist/collections/iset-mapped.mjs.map +1 -1
- package/dist/collections/iset.d.mts +1 -1
- package/dist/collections/iset.d.mts.map +1 -1
- package/dist/collections/iset.mjs +1 -0
- package/dist/collections/iset.mjs.map +1 -1
- package/dist/entry-point.mjs +1 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functional/optional/impl/optional-is-optional.d.mts +1 -1
- package/dist/functional/optional/impl/optional-is-optional.d.mts.map +1 -1
- package/dist/functional/optional/impl/optional-is-optional.mjs +6 -5
- package/dist/functional/optional/impl/optional-is-optional.mjs.map +1 -1
- package/dist/functional/optional/impl/optional-some.d.mts.map +1 -1
- package/dist/functional/optional/impl/optional-some.mjs.map +1 -1
- package/dist/functional/optional/impl/optional-zip.d.mts +1 -1
- package/dist/functional/optional/impl/optional-zip.mjs +1 -1
- package/dist/functional/result/impl/result-err.d.mts.map +1 -1
- package/dist/functional/result/impl/result-err.mjs.map +1 -1
- package/dist/functional/result/impl/result-is-result.d.mts +1 -1
- package/dist/functional/result/impl/result-is-result.mjs +1 -1
- package/dist/functional/result/impl/result-ok.d.mts.map +1 -1
- package/dist/functional/result/impl/result-ok.mjs.map +1 -1
- package/dist/functional/result/impl/result-unwrap-err-throw.mjs +1 -0
- package/dist/functional/result/impl/result-unwrap-err-throw.mjs.map +1 -1
- package/dist/functional/result/impl/result-unwrap-throw.mjs +1 -0
- package/dist/functional/result/impl/result-unwrap-throw.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-err.d.mts.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-err.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.d.mts +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.mjs +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-ok.d.mts.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-ok.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.mjs +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.mjs +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.mjs +1 -0
- package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-warn.d.mts.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-warn.mjs.map +1 -1
- package/dist/guard/has-key.d.mts +3 -1
- package/dist/guard/has-key.d.mts.map +1 -1
- package/dist/guard/has-key.mjs +6 -2
- package/dist/guard/has-key.mjs.map +1 -1
- package/dist/guard/is-non-null-object.d.mts.map +1 -1
- package/dist/guard/is-non-null-object.mjs +3 -1
- package/dist/guard/is-non-null-object.mjs.map +1 -1
- package/dist/guard/is-record.d.mts +2 -2
- package/dist/guard/is-record.mjs +2 -2
- package/dist/guard/is-type.d.mts +15 -15
- package/dist/guard/is-type.mjs +15 -15
- package/dist/guard/key-is-in.d.mts.map +1 -1
- package/dist/guard/key-is-in.mjs +3 -1
- package/dist/guard/key-is-in.mjs.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/json/json.d.mts +3 -3
- package/dist/json/json.mjs +4 -3
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-safe-int.mjs +2 -2
- package/dist/number/branded-types/positive-safe-int.mjs +1 -1
- package/dist/number/branded-types/safe-int.mjs +2 -2
- package/dist/number/branded-types/safe-uint.mjs +1 -1
- package/dist/number/num.mjs +1 -1
- package/dist/object/object.d.mts +8 -8
- package/dist/object/object.d.mts.map +1 -1
- package/dist/object/object.mjs +7 -6
- package/dist/object/object.mjs.map +1 -1
- package/dist/others/fast-deep-equal.d.mts +8 -0
- package/dist/others/fast-deep-equal.d.mts.map +1 -0
- package/dist/others/fast-deep-equal.mjs +72 -0
- package/dist/others/fast-deep-equal.mjs.map +1 -0
- package/dist/others/index.d.mts +1 -0
- package/dist/others/index.d.mts.map +1 -1
- package/dist/others/index.mjs +1 -0
- package/dist/others/index.mjs.map +1 -1
- package/dist/others/memoize-function.d.mts +3 -2
- package/dist/others/memoize-function.d.mts.map +1 -1
- package/dist/others/memoize-function.mjs +10 -39
- package/dist/others/memoize-function.mjs.map +1 -1
- package/package.json +22 -17
- package/src/array/impl/array-utils-creation.test.mts +13 -10
- package/src/array/impl/array-utils-element-access.mts +5 -5
- package/src/array/impl/array-utils-element-access.test.mts +5 -5
- package/src/array/impl/array-utils-iterators.mts +1 -1
- package/src/array/impl/array-utils-iterators.test.mts +6 -6
- package/src/array/impl/array-utils-modification.mts +4 -4
- package/src/array/impl/array-utils-modification.test.mts +12 -12
- package/src/array/impl/array-utils-overload-type-error.test.mts +1 -1
- package/src/array/impl/array-utils-reducing-value.mts +6 -5
- package/src/array/impl/array-utils-reducing-value.test.mts +9 -9
- package/src/array/impl/array-utils-search.mts +8 -8
- package/src/array/impl/array-utils-search.test.mts +35 -35
- package/src/array/impl/array-utils-set-op.mts +1 -0
- package/src/array/impl/array-utils-set-op.test.mts +2 -2
- package/src/array/impl/array-utils-size.mts +1 -1
- package/src/array/impl/array-utils-size.test.mts +1 -1
- package/src/array/impl/array-utils-slice-clamped.mts +1 -1
- package/src/array/impl/array-utils-slice-clamped.test.mts +5 -5
- package/src/array/impl/array-utils-slicing.mts +3 -3
- package/src/array/impl/array-utils-slicing.test.mts +5 -5
- package/src/array/impl/array-utils-transformation.mts +1 -1
- package/src/array/impl/array-utils-transformation.test.mts +53 -53
- package/src/array/impl/array-utils-validation.mts +18 -10
- package/src/array/impl/array-utils-validation.test.mts +34 -29
- package/src/array/impl/array.test.mts +1 -1
- package/src/collections/imap-mapped.test.mts +9 -9
- package/src/collections/imap.mts +20 -17
- package/src/collections/imap.test.mts +6 -6
- package/src/collections/iset-mapped.mts +7 -6
- package/src/collections/iset-mapped.test.mts +6 -6
- package/src/collections/iset.mts +6 -5
- package/src/collections/queue.test.mts +2 -1
- package/src/collections/stack.test.mts +3 -3
- package/src/functional/optional/impl/optional-is-optional.mts +6 -6
- package/src/functional/optional/impl/optional-some.mts +5 -4
- package/src/functional/optional/impl/optional-zip.mts +1 -1
- package/src/functional/result/impl/result-err.mts +5 -4
- package/src/functional/result/impl/result-is-result.mts +1 -1
- package/src/functional/result/impl/result-ok.mts +5 -4
- package/src/functional/result.test.mts +2 -2
- package/src/functional/ternary-result/impl/ternary-result-err.mts +5 -4
- package/src/functional/ternary-result/impl/ternary-result-is-ternary-result.mts +1 -1
- package/src/functional/ternary-result/impl/ternary-result-ok.mts +5 -4
- package/src/functional/ternary-result/impl/ternary-result-warn.mts +6 -5
- package/src/guard/has-key.mts +6 -2
- package/src/guard/is-error.test.mts +1 -1
- package/src/guard/is-non-empty-string.test.mts +1 -1
- package/src/guard/is-non-null-object.mts +1 -0
- package/src/guard/is-non-null-object.test.mts +4 -3
- package/src/guard/is-primitive.test.mts +1 -1
- package/src/guard/is-record.mts +2 -2
- package/src/guard/is-record.test.mts +2 -2
- package/src/guard/is-type.mts +15 -15
- package/src/guard/is-type.test.mts +2 -2
- package/src/guard/key-is-in.mts +3 -1
- package/src/json/json.mts +4 -3
- package/src/json/json.test.mts +20 -19
- package/src/number/branded-types/non-zero-safe-int.mts +2 -2
- package/src/number/branded-types/positive-safe-int.mts +1 -1
- package/src/number/branded-types/safe-int.mts +2 -2
- package/src/number/branded-types/safe-uint.mts +1 -1
- package/src/number/num.mts +1 -1
- package/src/object/object.mts +9 -8
- package/src/object/object.test.mts +12 -7
- package/src/others/cast-mutable.test.mts +3 -3
- package/src/others/cast-readonly.test.mts +8 -5
- package/src/others/fast-deep-equal.mts +98 -0
- package/src/others/fast-deep-equal.test.mts +769 -0
- package/src/others/index.mts +1 -0
- package/src/others/map-nullable.test.mts +8 -8
- package/src/others/memoize-function.mts +35 -17
- package/src/others/memoize-function.test.mts +45 -8
- package/src/others/unknown-to-string.test.mts +8 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRecord } from '../../../guard/index.mjs';
|
|
1
|
+
import { hasKey, isRecord } from '../../../guard/index.mjs';
|
|
2
2
|
import { NoneTypeTagName, SomeTypeTagName } from './tag.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -9,7 +9,7 @@ import { NoneTypeTagName, SomeTypeTagName } from './tag.mjs';
|
|
|
9
9
|
* ```ts
|
|
10
10
|
* const maybeOptional = Optional.some('value');
|
|
11
11
|
*
|
|
12
|
-
* const notOptional = { $$tag: 'ts-data-forge::Optional.some' };
|
|
12
|
+
* const notOptional = { $$tag: 'ts-data-forge::Optional.some' } as const;
|
|
13
13
|
*
|
|
14
14
|
* assert.isTrue(Optional.isOptional(maybeOptional));
|
|
15
15
|
*
|
|
@@ -23,7 +23,7 @@ export const isOptional = (
|
|
|
23
23
|
maybeOptional: unknown,
|
|
24
24
|
): maybeOptional is Optional<unknown> =>
|
|
25
25
|
isRecord(maybeOptional) &&
|
|
26
|
-
|
|
27
|
-
((maybeOptional
|
|
28
|
-
|
|
29
|
-
maybeOptional
|
|
26
|
+
hasKey(maybeOptional, '$$tag') &&
|
|
27
|
+
((maybeOptional.$$tag === SomeTypeTagName &&
|
|
28
|
+
hasKey(maybeOptional, 'value')) ||
|
|
29
|
+
maybeOptional.$$tag === NoneTypeTagName);
|
|
@@ -19,7 +19,8 @@ import { SomeTypeTagName } from './tag.mjs';
|
|
|
19
19
|
* @param value The value to wrap in an {@link Some}.
|
|
20
20
|
* @returns An {@link Some}<S> containing the value.
|
|
21
21
|
*/
|
|
22
|
-
export const some = <const S,>(value: S): Some<S> =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
export const some = <const S,>(value: S): Some<S> =>
|
|
23
|
+
({
|
|
24
|
+
$$tag: SomeTypeTagName,
|
|
25
|
+
value,
|
|
26
|
+
}) as const;
|
|
@@ -14,7 +14,7 @@ import { some } from './optional-some.mjs';
|
|
|
14
14
|
* assert.isTrue(Optional.isSome(zipped));
|
|
15
15
|
*
|
|
16
16
|
* if (Optional.isSome(zipped)) {
|
|
17
|
-
* const expected: readonly [string, number] = ['left', 1];
|
|
17
|
+
* const expected: readonly [string, number] = ['left', 1] as const;
|
|
18
18
|
*
|
|
19
19
|
* assert.deepStrictEqual(zipped.value, expected);
|
|
20
20
|
* }
|
|
@@ -25,7 +25,8 @@ import { ErrTypeTagName } from './tag.mjs';
|
|
|
25
25
|
* @param value The error value.
|
|
26
26
|
* @returns A `Result.Err<E>` containing the value.
|
|
27
27
|
*/
|
|
28
|
-
export const err = <const E,>(value: E): Err<E> =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
export const err = <const E,>(value: E): Err<E> =>
|
|
29
|
+
({
|
|
30
|
+
$$tag: ErrTypeTagName,
|
|
31
|
+
value,
|
|
32
|
+
}) as const;
|
|
@@ -11,7 +11,7 @@ import { ErrTypeTagName, OkTypeTagName } from './tag.mjs';
|
|
|
11
11
|
*
|
|
12
12
|
* const errValue = Result.err(new Error('failure'));
|
|
13
13
|
*
|
|
14
|
-
* const notResult = { $$tag: 'ts-data-forge::Result.ok' };
|
|
14
|
+
* const notResult = { $$tag: 'ts-data-forge::Result.ok' } as const;
|
|
15
15
|
*
|
|
16
16
|
* assert.isTrue(Result.isResult(okValue));
|
|
17
17
|
*
|
|
@@ -25,7 +25,8 @@ import { OkTypeTagName } from './tag.mjs';
|
|
|
25
25
|
* @param value The success value.
|
|
26
26
|
* @returns A `Result.Ok<S>` containing the value.
|
|
27
27
|
*/
|
|
28
|
-
export const ok = <const S,>(value: S): Ok<S> =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
export const ok = <const S,>(value: S): Ok<S> =>
|
|
29
|
+
({
|
|
30
|
+
$$tag: OkTypeTagName,
|
|
31
|
+
value,
|
|
32
|
+
}) as const;
|
|
@@ -821,7 +821,7 @@ describe('Result test', () => {
|
|
|
821
821
|
});
|
|
822
822
|
|
|
823
823
|
test('should return Ok with object when function succeeds', () => {
|
|
824
|
-
const obj = { name: 'test', value: 123 };
|
|
824
|
+
const obj = { name: 'test', value: 123 } as const;
|
|
825
825
|
|
|
826
826
|
const result = Result.fromThrowable(() => obj);
|
|
827
827
|
|
|
@@ -901,7 +901,7 @@ describe('Result test', () => {
|
|
|
901
901
|
});
|
|
902
902
|
|
|
903
903
|
test('should work with array access', () => {
|
|
904
|
-
const arr = [1, 2, 3];
|
|
904
|
+
const arr = [1, 2, 3] as readonly number[];
|
|
905
905
|
|
|
906
906
|
// This won't throw, but demonstrates the pattern
|
|
907
907
|
const result = Result.fromThrowable(() => {
|
|
@@ -13,7 +13,8 @@ import { ErrTypeTagName } from './tag.mjs';
|
|
|
13
13
|
* assert.isTrue(TernaryResult.isErr(failure));
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
|
-
export const err = <const E,>(value: E): TernaryErr<E> =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
export const err = <const E,>(value: E): TernaryErr<E> =>
|
|
17
|
+
({
|
|
18
|
+
$$tag: ErrTypeTagName,
|
|
19
|
+
value,
|
|
20
|
+
}) as const;
|
|
@@ -11,7 +11,7 @@ import { ErrTypeTagName, OkTypeTagName, WarnTypeTagName } from './tag.mjs';
|
|
|
11
11
|
*
|
|
12
12
|
* const warnValue = TernaryResult.warn('done', 'retry later');
|
|
13
13
|
*
|
|
14
|
-
* const notResult = { $$tag: 'ts-data-forge::Result.ok' };
|
|
14
|
+
* const notResult = { $$tag: 'ts-data-forge::Result.ok' } as const;
|
|
15
15
|
*
|
|
16
16
|
* assert.isTrue(TernaryResult.isTernaryResult(okValue));
|
|
17
17
|
*
|
|
@@ -14,7 +14,8 @@ import { OkTypeTagName } from './tag.mjs';
|
|
|
14
14
|
* });
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
|
-
export const ok = <const S,>(value: S): TernaryOk<S> =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
export const ok = <const S,>(value: S): TernaryOk<S> =>
|
|
18
|
+
({
|
|
19
|
+
$$tag: OkTypeTagName,
|
|
20
|
+
value,
|
|
21
|
+
}) as const;
|
|
@@ -19,8 +19,9 @@ import { WarnTypeTagName } from './tag.mjs';
|
|
|
19
19
|
export const warn = <const S, const W>(
|
|
20
20
|
value: S,
|
|
21
21
|
warning: W,
|
|
22
|
-
): TernaryWarn<S, W> =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
): TernaryWarn<S, W> =>
|
|
23
|
+
({
|
|
24
|
+
$$tag: WarnTypeTagName,
|
|
25
|
+
value,
|
|
26
|
+
warning,
|
|
27
|
+
}) as const;
|
package/src/guard/has-key.mts
CHANGED
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
* @example
|
|
18
18
|
*
|
|
19
19
|
* ```ts
|
|
20
|
-
* const maybeUser: Readonly<{ id?: number; name?: string }> = {
|
|
20
|
+
* const maybeUser: Readonly<{ id?: number; name?: string }> = {
|
|
21
|
+
* id: 42,
|
|
22
|
+
* } as const;
|
|
21
23
|
*
|
|
22
24
|
* if (hasKey(maybeUser, 'id')) {
|
|
23
25
|
* // `maybeUser` is now known to have an `id` property.
|
|
@@ -43,7 +45,9 @@ export const hasKey = <
|
|
|
43
45
|
>(
|
|
44
46
|
obj: R,
|
|
45
47
|
key: K,
|
|
46
|
-
): obj is HasKeyReturnType<R, K> =>
|
|
48
|
+
): obj is HasKeyReturnType<R, K> =>
|
|
49
|
+
// eslint-disable-next-line ts-data-forge/prefer-is-record-and-has-key
|
|
50
|
+
Object.hasOwn(obj, key);
|
|
47
51
|
|
|
48
52
|
/**
|
|
49
53
|
* @internal
|
|
@@ -73,7 +73,7 @@ describe(isNonNullObject, () => {
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
test('should act as a type guard', () => {
|
|
76
|
-
const value: unknown = { test: true };
|
|
76
|
+
const value: unknown = { test: true } as const;
|
|
77
77
|
|
|
78
78
|
if (isNonNullObject(value)) {
|
|
79
79
|
expectType<typeof value, object>('=');
|
|
@@ -81,7 +81,8 @@ describe(isNonNullObject, () => {
|
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
test('should narrow nullable object types', () => {
|
|
84
|
-
const nullable: UnknownRecord | null =
|
|
84
|
+
const nullable: UnknownRecord | null =
|
|
85
|
+
Math.random() > 0.5 ? ({} as const) : null;
|
|
85
86
|
|
|
86
87
|
if (isNonNullObject(nullable)) {
|
|
87
88
|
expectType<typeof nullable, UnknownRecord>('=');
|
|
@@ -98,7 +99,7 @@ describe(isNonNullObject, () => {
|
|
|
98
99
|
[],
|
|
99
100
|
() => {},
|
|
100
101
|
true,
|
|
101
|
-
];
|
|
102
|
+
] as const;
|
|
102
103
|
|
|
103
104
|
const objects = mixed.filter(isNonNullObject);
|
|
104
105
|
|
package/src/guard/is-record.mts
CHANGED
|
@@ -25,7 +25,7 @@ import { isNonNullObject } from './is-non-null-object.mjs';
|
|
|
25
25
|
* @example
|
|
26
26
|
*
|
|
27
27
|
* ```ts
|
|
28
|
-
* const entries: readonly unknown[] = [{ id: 1 }, 'str', 0, null];
|
|
28
|
+
* const entries: readonly unknown[] = [{ id: 1 }, 'str', 0, null] as const;
|
|
29
29
|
*
|
|
30
30
|
* const records = entries.filter(isRecord);
|
|
31
31
|
*
|
|
@@ -58,7 +58,7 @@ export const isRecord = (u: unknown): u is UnknownRecord => isNonNullObject(u);
|
|
|
58
58
|
*
|
|
59
59
|
* @example
|
|
60
60
|
* ```ts
|
|
61
|
-
* const obj: unknown = { foo: 1 };
|
|
61
|
+
* const obj: unknown = { foo: 1 } as const;
|
|
62
62
|
*
|
|
63
63
|
* if (isMutableRecord(obj)) {
|
|
64
64
|
* obj['bar'] = 2; // Safe: obj is now known to be a mutable record
|
|
@@ -4,7 +4,7 @@ import { isRecord } from './is-record.mjs';
|
|
|
4
4
|
describe(isRecord, () => {
|
|
5
5
|
describe('arrays are Records', () => {
|
|
6
6
|
test('number[] is assignable to Record<number, unknown>', () => {
|
|
7
|
-
const arr: Record<number, unknown> = [1, 2, 3];
|
|
7
|
+
const arr: Record<number, unknown> = [1, 2, 3] as const;
|
|
8
8
|
|
|
9
9
|
const unk: unknown = arr;
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ describe(isRecord, () => {
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
test('string[] is assignable to Record<number, unknown>', () => {
|
|
17
|
-
const arr: Record<number, unknown> = ['1', '2', '3'];
|
|
17
|
+
const arr: Record<number, unknown> = ['1', '2', '3'] as const;
|
|
18
18
|
|
|
19
19
|
const unk: unknown = arr;
|
|
20
20
|
|
package/src/guard/is-type.mts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @example
|
|
10
10
|
*
|
|
11
11
|
* ```ts
|
|
12
|
-
* const values: readonly (number | undefined)[] = [1, undefined, 2];
|
|
12
|
+
* const values: readonly (number | undefined)[] = [1, undefined, 2] as const;
|
|
13
13
|
*
|
|
14
14
|
* const undefinedValues = values.filter(isUndefined);
|
|
15
15
|
*
|
|
@@ -34,7 +34,7 @@ export const isUndefined = (u: unknown): u is undefined => u === undefined;
|
|
|
34
34
|
* @example
|
|
35
35
|
*
|
|
36
36
|
* ```ts
|
|
37
|
-
* const values: readonly (number | undefined)[] = [1, undefined, 2];
|
|
37
|
+
* const values: readonly (number | undefined)[] = [1, undefined, 2] as const;
|
|
38
38
|
*
|
|
39
39
|
* const definedValues = values.filter(isNotUndefined);
|
|
40
40
|
*
|
|
@@ -60,7 +60,7 @@ export const isNotUndefined = <T,>(u: T): u is RelaxedExclude<T, undefined> =>
|
|
|
60
60
|
* @example
|
|
61
61
|
*
|
|
62
62
|
* ```ts
|
|
63
|
-
* const flags: readonly unknown[] = [true, 'no', false];
|
|
63
|
+
* const flags: readonly unknown[] = [true, 'no', false] as const;
|
|
64
64
|
*
|
|
65
65
|
* const booleans = flags.filter(isBoolean);
|
|
66
66
|
*
|
|
@@ -84,7 +84,7 @@ export const isBoolean = (u: unknown): u is boolean => typeof u === 'boolean';
|
|
|
84
84
|
* @example
|
|
85
85
|
*
|
|
86
86
|
* ```ts
|
|
87
|
-
* const flags: readonly unknown[] = [true, 'no', false];
|
|
87
|
+
* const flags: readonly unknown[] = [true, 'no', false] as const;
|
|
88
88
|
*
|
|
89
89
|
* const nonBooleans = flags.filter(isNotBoolean);
|
|
90
90
|
*
|
|
@@ -111,7 +111,7 @@ export const isNotBoolean = <T,>(u: T): u is RelaxedExclude<T, boolean> =>
|
|
|
111
111
|
* @example
|
|
112
112
|
*
|
|
113
113
|
* ```ts
|
|
114
|
-
* const mixed: readonly unknown[] = [1, '2', 3];
|
|
114
|
+
* const mixed: readonly unknown[] = [1, '2', 3] as const;
|
|
115
115
|
*
|
|
116
116
|
* const numbers = mixed.filter(isNumber);
|
|
117
117
|
*
|
|
@@ -135,7 +135,7 @@ export const isNumber = (u: unknown): u is number => typeof u === 'number';
|
|
|
135
135
|
* @example
|
|
136
136
|
*
|
|
137
137
|
* ```ts
|
|
138
|
-
* const mixed: readonly unknown[] = [1, '2', 3];
|
|
138
|
+
* const mixed: readonly unknown[] = [1, '2', 3] as const;
|
|
139
139
|
*
|
|
140
140
|
* const nonNumbers = mixed.filter(isNotNumber);
|
|
141
141
|
*
|
|
@@ -161,7 +161,7 @@ export const isNotNumber = <T,>(u: T): u is RelaxedExclude<T, number> =>
|
|
|
161
161
|
* @example
|
|
162
162
|
*
|
|
163
163
|
* ```ts
|
|
164
|
-
* const values: readonly unknown[] = [1n, 2, 3n];
|
|
164
|
+
* const values: readonly unknown[] = [1n, 2, 3n] as const;
|
|
165
165
|
*
|
|
166
166
|
* const bigints = values.filter(isBigint);
|
|
167
167
|
*
|
|
@@ -185,7 +185,7 @@ export const isBigint = (u: unknown): u is bigint => typeof u === 'bigint';
|
|
|
185
185
|
* @example
|
|
186
186
|
*
|
|
187
187
|
* ```ts
|
|
188
|
-
* const values: readonly unknown[] = [1n, 2, 3n];
|
|
188
|
+
* const values: readonly unknown[] = [1n, 2, 3n] as const;
|
|
189
189
|
*
|
|
190
190
|
* const nonBigints = values.filter(isNotBigint);
|
|
191
191
|
*
|
|
@@ -212,7 +212,7 @@ export const isNotBigint = <T,>(u: T): u is RelaxedExclude<T, bigint> =>
|
|
|
212
212
|
* @example
|
|
213
213
|
*
|
|
214
214
|
* ```ts
|
|
215
|
-
* const values: readonly unknown[] = ['Ada', 42, 'Lovelace'];
|
|
215
|
+
* const values: readonly unknown[] = ['Ada', 42, 'Lovelace'] as const;
|
|
216
216
|
*
|
|
217
217
|
* const strings = values.filter(isString);
|
|
218
218
|
*
|
|
@@ -236,7 +236,7 @@ export const isString = (u: unknown): u is string => typeof u === 'string';
|
|
|
236
236
|
* @example
|
|
237
237
|
*
|
|
238
238
|
* ```ts
|
|
239
|
-
* const values: readonly unknown[] = ['Ada', 42, 'Lovelace'];
|
|
239
|
+
* const values: readonly unknown[] = ['Ada', 42, 'Lovelace'] as const;
|
|
240
240
|
*
|
|
241
241
|
* const nonStrings = values.filter(isNotString);
|
|
242
242
|
*
|
|
@@ -266,7 +266,7 @@ export const isNotString = <T,>(u: T): u is RelaxedExclude<T, string> =>
|
|
|
266
266
|
*
|
|
267
267
|
* const shared = Symbol.for('shared');
|
|
268
268
|
*
|
|
269
|
-
* const tokens: readonly unknown[] = [id, 'shared', shared];
|
|
269
|
+
* const tokens: readonly unknown[] = [id, 'shared', shared] as const;
|
|
270
270
|
*
|
|
271
271
|
* const symbols = tokens.filter(isSymbol);
|
|
272
272
|
*
|
|
@@ -292,7 +292,7 @@ export const isSymbol = (u: unknown): u is symbol => typeof u === 'symbol';
|
|
|
292
292
|
* ```ts
|
|
293
293
|
* const id = Symbol('id');
|
|
294
294
|
*
|
|
295
|
-
* const tokens: readonly unknown[] = [id, 'shared'];
|
|
295
|
+
* const tokens: readonly unknown[] = [id, 'shared'] as const;
|
|
296
296
|
*
|
|
297
297
|
* const nonSymbols = tokens.filter(isNotSymbol);
|
|
298
298
|
*
|
|
@@ -343,7 +343,7 @@ export const isNull = (u: unknown): u is null => u === null;
|
|
|
343
343
|
* @example
|
|
344
344
|
*
|
|
345
345
|
* ```ts
|
|
346
|
-
* const values: readonly (number | null)[] = [null, 5];
|
|
346
|
+
* const values: readonly (number | null)[] = [null, 5] as const;
|
|
347
347
|
*
|
|
348
348
|
* const nonNullValues = values.filter(isNotNull);
|
|
349
349
|
*
|
|
@@ -376,7 +376,7 @@ export const isNotNull = <T,>(u: T | null): u is T => u !== null;
|
|
|
376
376
|
* 'Ada',
|
|
377
377
|
* null,
|
|
378
378
|
* undefined,
|
|
379
|
-
* ];
|
|
379
|
+
* ] as const;
|
|
380
380
|
*
|
|
381
381
|
* const nullishValues = values.filter(isNullish);
|
|
382
382
|
*
|
|
@@ -409,7 +409,7 @@ export const isNullish = (u: unknown): u is null | undefined => u == null;
|
|
|
409
409
|
* 'Ada',
|
|
410
410
|
* null,
|
|
411
411
|
* undefined,
|
|
412
|
-
* ];
|
|
412
|
+
* ] as const;
|
|
413
413
|
*
|
|
414
414
|
* const definedValues = values.filter(isNonNullish);
|
|
415
415
|
*
|
|
@@ -572,7 +572,7 @@ describe(isNonNullish, () => {
|
|
|
572
572
|
'world',
|
|
573
573
|
undefined,
|
|
574
574
|
'test',
|
|
575
|
-
];
|
|
575
|
+
] as const;
|
|
576
576
|
|
|
577
577
|
const definedItems = items.filter(isNonNullish);
|
|
578
578
|
|
|
@@ -618,7 +618,7 @@ describe('type guard behavior in complex scenarios', () => {
|
|
|
618
618
|
undefined,
|
|
619
619
|
false,
|
|
620
620
|
123,
|
|
621
|
-
];
|
|
621
|
+
] as const;
|
|
622
622
|
|
|
623
623
|
const nonNullish = mixed.filter(isNonNullish);
|
|
624
624
|
|
package/src/guard/key-is-in.mts
CHANGED
package/src/json/json.mts
CHANGED
|
@@ -93,7 +93,7 @@ export namespace Json {
|
|
|
93
93
|
* @example
|
|
94
94
|
*
|
|
95
95
|
* ```ts
|
|
96
|
-
* const data = { name: 'Bob', age: 25, active: true };
|
|
96
|
+
* const data = { name: 'Bob', age: 25, active: true } as const;
|
|
97
97
|
*
|
|
98
98
|
* // Basic stringify
|
|
99
99
|
* const basic = Json.stringify(data);
|
|
@@ -177,7 +177,7 @@ export namespace Json {
|
|
|
177
177
|
* email: 'charlie@example.com',
|
|
178
178
|
* password: 'secret123',
|
|
179
179
|
* role: 'admin',
|
|
180
|
-
* };
|
|
180
|
+
* } as const;
|
|
181
181
|
*
|
|
182
182
|
* // Select only safe properties to serialize
|
|
183
183
|
* const safeJson = Json.stringifySelected(user, ['id', 'name', 'role']);
|
|
@@ -262,7 +262,7 @@ export namespace Json {
|
|
|
262
262
|
* alpha: 'a',
|
|
263
263
|
* beta: 'b',
|
|
264
264
|
* },
|
|
265
|
-
* };
|
|
265
|
+
* } as const;
|
|
266
266
|
*
|
|
267
267
|
* // Keys will be sorted alphabetically at all levels
|
|
268
268
|
* const sorted = Json.stringifySortedKey(unorderedData);
|
|
@@ -354,6 +354,7 @@ const keysDeepImpl = (
|
|
|
354
354
|
keysDeepImpl(o, mut_keys);
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
+
// eslint-disable-next-line ts-data-forge/prefer-arr-is-array
|
|
357
358
|
if (Array.isArray(o)) {
|
|
358
359
|
for (const li of o) {
|
|
359
360
|
if (isRecord(li)) {
|
package/src/json/json.test.mts
CHANGED
|
@@ -54,7 +54,7 @@ describe('parse', () => {
|
|
|
54
54
|
array: [1, 2, { level3: 'deep' }],
|
|
55
55
|
},
|
|
56
56
|
},
|
|
57
|
-
};
|
|
57
|
+
} as const;
|
|
58
58
|
|
|
59
59
|
assert.deepStrictEqual(Json.parse(json), Result.ok(expected));
|
|
60
60
|
});
|
|
@@ -227,7 +227,7 @@ describe('stringify', () => {
|
|
|
227
227
|
array: [1, 2, { level3: 'deep' }],
|
|
228
228
|
},
|
|
229
229
|
},
|
|
230
|
-
};
|
|
230
|
+
} as const;
|
|
231
231
|
|
|
232
232
|
assert.deepStrictEqual(
|
|
233
233
|
Json.stringify(nested),
|
|
@@ -301,7 +301,7 @@ describe('stringify', () => {
|
|
|
301
301
|
test('should handle objects with toJSON method', () => {
|
|
302
302
|
const obj = {
|
|
303
303
|
toJSON: () => ({ custom: 'value' }),
|
|
304
|
-
};
|
|
304
|
+
} as const;
|
|
305
305
|
|
|
306
306
|
assert.deepStrictEqual(
|
|
307
307
|
Json.stringify(obj),
|
|
@@ -333,7 +333,7 @@ describe('stringify', () => {
|
|
|
333
333
|
name: 'John',
|
|
334
334
|
password: 'secret123',
|
|
335
335
|
email: 'john@example.com',
|
|
336
|
-
};
|
|
336
|
+
} as const;
|
|
337
337
|
|
|
338
338
|
const secureReplacer = (key: string, value: unknown): unknown => {
|
|
339
339
|
if (key === 'password') return '[REDACTED]';
|
|
@@ -351,7 +351,7 @@ describe('stringify', () => {
|
|
|
351
351
|
});
|
|
352
352
|
|
|
353
353
|
test('should format output with space parameter (number)', () => {
|
|
354
|
-
const data = { a: 1, b: 2 };
|
|
354
|
+
const data = { a: 1, b: 2 } as const;
|
|
355
355
|
|
|
356
356
|
const result = Json.stringify(data, undefined, 2);
|
|
357
357
|
|
|
@@ -363,7 +363,7 @@ describe('stringify', () => {
|
|
|
363
363
|
});
|
|
364
364
|
|
|
365
365
|
test('should format output with space parameter (string)', () => {
|
|
366
|
-
const data = { a: 1, b: 2 };
|
|
366
|
+
const data = { a: 1, b: 2 } as const;
|
|
367
367
|
|
|
368
368
|
const result = Json.stringify(data, undefined, '\t');
|
|
369
369
|
|
|
@@ -383,7 +383,7 @@ describe('stringifySelected', () => {
|
|
|
383
383
|
email: 'alice@example.com',
|
|
384
384
|
password: 'secret123',
|
|
385
385
|
lastLogin: '2023-12-01',
|
|
386
|
-
};
|
|
386
|
+
} as const;
|
|
387
387
|
|
|
388
388
|
const result = Json.stringifySelected(user, ['id', 'name', 'email']);
|
|
389
389
|
|
|
@@ -411,7 +411,7 @@ describe('stringifySelected', () => {
|
|
|
411
411
|
{ id: 2, name: 'Bob', secret: 'hidden2' },
|
|
412
412
|
],
|
|
413
413
|
metadata: { total: 2, page: 1, internal: 'secret' },
|
|
414
|
-
};
|
|
414
|
+
} as const;
|
|
415
415
|
|
|
416
416
|
const result = Json.stringifySelected(data, [
|
|
417
417
|
'users',
|
|
@@ -453,7 +453,7 @@ describe('stringifySelected', () => {
|
|
|
453
453
|
[1, 2, 3, 4],
|
|
454
454
|
[5, 6, 7, 8],
|
|
455
455
|
[9, 10, 11, 12],
|
|
456
|
-
];
|
|
456
|
+
] as const;
|
|
457
457
|
|
|
458
458
|
const result = Json.stringifySelected(matrix, [0, 1]);
|
|
459
459
|
|
|
@@ -465,13 +465,14 @@ describe('stringifySelected', () => {
|
|
|
465
465
|
|
|
466
466
|
// Note: stringifySelected works with JSON.stringify's replacer parameter
|
|
467
467
|
// which may not work as expected with arrays
|
|
468
|
+
// eslint-disable-next-line ts-data-forge/prefer-arr-is-array
|
|
468
469
|
assert.isTrue(Array.isArray(parsed));
|
|
469
470
|
|
|
470
471
|
expect(parsed).toHaveLength(3);
|
|
471
472
|
});
|
|
472
473
|
|
|
473
474
|
test('should handle formatting with space parameter', () => {
|
|
474
|
-
const data = { a: 1, b: { c: 2 } };
|
|
475
|
+
const data = { a: 1, b: { c: 2 } } as const;
|
|
475
476
|
|
|
476
477
|
const result = Json.stringifySelected(data, ['a', 'b', 'c'], 2);
|
|
477
478
|
|
|
@@ -483,7 +484,7 @@ describe('stringifySelected', () => {
|
|
|
483
484
|
});
|
|
484
485
|
|
|
485
486
|
test('should handle empty selection array', () => {
|
|
486
|
-
const data = { a: 1, b: 2, c: 3 };
|
|
487
|
+
const data = { a: 1, b: 2, c: 3 } as const;
|
|
487
488
|
|
|
488
489
|
const result = Json.stringifySelected(data, []);
|
|
489
490
|
|
|
@@ -493,7 +494,7 @@ describe('stringifySelected', () => {
|
|
|
493
494
|
});
|
|
494
495
|
|
|
495
496
|
test('should handle undefined properties parameter', () => {
|
|
496
|
-
const data = { a: 1, b: 2 };
|
|
497
|
+
const data = { a: 1, b: 2 } as const;
|
|
497
498
|
|
|
498
499
|
const result = Json.stringifySelected(data, undefined);
|
|
499
500
|
|
|
@@ -532,7 +533,7 @@ describe('stringifySortedKey', () => {
|
|
|
532
533
|
apple: 'fruit',
|
|
533
534
|
banana: 'fruit',
|
|
534
535
|
aardvark: 'animal',
|
|
535
|
-
};
|
|
536
|
+
} as const;
|
|
536
537
|
|
|
537
538
|
const result = Json.stringifySortedKey(unsortedObj);
|
|
538
539
|
|
|
@@ -558,7 +559,7 @@ describe('stringifySortedKey', () => {
|
|
|
558
559
|
theme: 'dark',
|
|
559
560
|
language: 'en',
|
|
560
561
|
},
|
|
561
|
-
};
|
|
562
|
+
} as const;
|
|
562
563
|
|
|
563
564
|
const result = Json.stringifySortedKey(nestedObj);
|
|
564
565
|
|
|
@@ -598,7 +599,7 @@ describe('stringifySortedKey', () => {
|
|
|
598
599
|
created: '2023-12-01',
|
|
599
600
|
author: 'system',
|
|
600
601
|
},
|
|
601
|
-
};
|
|
602
|
+
} as const;
|
|
602
603
|
|
|
603
604
|
const result = Json.stringifySortedKey(dataWithArrays);
|
|
604
605
|
|
|
@@ -639,7 +640,7 @@ describe('stringifySortedKey', () => {
|
|
|
639
640
|
});
|
|
640
641
|
|
|
641
642
|
test('should handle formatting with space parameter', () => {
|
|
642
|
-
const obj = { b: 2, a: 1 };
|
|
643
|
+
const obj = { b: 2, a: 1 } as const;
|
|
643
644
|
|
|
644
645
|
const result = Json.stringifySortedKey(obj, 2);
|
|
645
646
|
|
|
@@ -653,9 +654,9 @@ describe('stringifySortedKey', () => {
|
|
|
653
654
|
});
|
|
654
655
|
|
|
655
656
|
test('should produce deterministic output', () => {
|
|
656
|
-
const obj1 = { c: 3, a: 1, b: 2 };
|
|
657
|
+
const obj1 = { c: 3, a: 1, b: 2 } as const;
|
|
657
658
|
|
|
658
|
-
const obj2 = { b: 2, a: 1, c: 3 };
|
|
659
|
+
const obj2 = { b: 2, a: 1, c: 3 } as const;
|
|
659
660
|
|
|
660
661
|
const result1 = Json.stringifySortedKey(obj1);
|
|
661
662
|
|
|
@@ -716,7 +717,7 @@ describe('stringifySortedKey', () => {
|
|
|
716
717
|
},
|
|
717
718
|
},
|
|
718
719
|
},
|
|
719
|
-
};
|
|
720
|
+
} as const;
|
|
720
721
|
|
|
721
722
|
const result = Json.stringifySortedKey(deep);
|
|
722
723
|
|
|
@@ -27,9 +27,9 @@ const {
|
|
|
27
27
|
>({
|
|
28
28
|
integerOrSafeInteger: 'SafeInteger',
|
|
29
29
|
nonZero: true,
|
|
30
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion, math/prefer-number-min-safe-integer
|
|
30
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion, math/prefer-number-min-safe-integer, ts-data-forge/prefer-as-int
|
|
31
31
|
MIN_VALUE: Number.MIN_SAFE_INTEGER as SafeInt,
|
|
32
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion, math/prefer-number-max-safe-integer
|
|
32
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion, math/prefer-number-max-safe-integer, ts-data-forge/prefer-as-int
|
|
33
33
|
MAX_VALUE: Number.MAX_SAFE_INTEGER as SafeUint,
|
|
34
34
|
typeNameInMessage,
|
|
35
35
|
} as const);
|
|
@@ -26,7 +26,7 @@ const {
|
|
|
26
26
|
>({
|
|
27
27
|
integerOrSafeInteger: 'SafeInteger',
|
|
28
28
|
MIN_VALUE: 1,
|
|
29
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion, math/prefer-number-max-safe-integer
|
|
29
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion, math/prefer-number-max-safe-integer, ts-data-forge/prefer-as-int
|
|
30
30
|
MAX_VALUE: Number.MAX_SAFE_INTEGER as SafeUint,
|
|
31
31
|
typeNameInMessage,
|
|
32
32
|
} as const);
|