ts-gems 4.0.0 → 4.0.2
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/docs/api/omit.md +6 -5
- package/docs/api/pick.md +6 -4
- package/docs/api.md +16 -3
- package/lib/mutable.d.ts +8 -6
- package/lib/omit-never.d.ts +9 -7
- package/lib/omit-undefined.d.ts +6 -4
- package/lib/omit.d.ts +9 -16
- package/lib/partial.d.ts +8 -6
- package/lib/pick.d.ts +1 -10
- package/lib/readonly.d.ts +21 -15
- package/lib/required.d.ts +27 -25
- package/lib/type-check.d.ts +8 -0
- package/package.json +1 -1
package/docs/api/omit.md
CHANGED
|
@@ -9,10 +9,11 @@ convention](../api.md#the-deep--deeper-convention) for `DeepOmitTypes`/
|
|
|
9
9
|
|
|
10
10
|
## `StrictOmit<T, X>`
|
|
11
11
|
|
|
12
|
-
Like the built-in `Omit<T, K>`, but
|
|
13
|
-
|
|
14
|
-
[`StrictPick`](pick.md#strictpickt-x),
|
|
15
|
-
|
|
12
|
+
Like the built-in `Omit<T, K>`, but `X` is constrained to `keyof T`, so a
|
|
13
|
+
typo in the key you're omitting is a compile error instead of a silent
|
|
14
|
+
no-op. Unlike [`StrictPick`](pick.md#strictpickt-x), it does **not** also
|
|
15
|
+
drop `never`-typed keys — only the key(s) named in `X` are removed, by
|
|
16
|
+
identity, regardless of their value type.
|
|
16
17
|
|
|
17
18
|
```ts
|
|
18
19
|
import type { StrictOmit } from 'ts-gems';
|
|
@@ -24,7 +25,7 @@ interface Row {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
type Result = StrictOmit<Row, 'b'>;
|
|
27
|
-
// { a?: number } - `
|
|
28
|
+
// { a?: number; c: never } - only `b` is removed
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
## `OmitFunctions<T>`
|
package/docs/api/pick.md
CHANGED
|
@@ -7,9 +7,11 @@ See [Omit](omit.md) for the inverse operations.
|
|
|
7
7
|
|
|
8
8
|
## `StrictPick<T, X>`
|
|
9
9
|
|
|
10
|
-
Like the built-in `Pick<T, K>`, but
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
Like the built-in `Pick<T, K>`, but `X` is constrained to `keyof T`, so a
|
|
11
|
+
typo in the key you're picking is a compile error instead of silently
|
|
12
|
+
producing `never`. It only selects by key identity — it does **not** also
|
|
13
|
+
drop `never`-typed keys, so it stays correct when `T` is still an open
|
|
14
|
+
generic type parameter (e.g. used inside another generic function).
|
|
13
15
|
|
|
14
16
|
```ts
|
|
15
17
|
import type { StrictPick } from 'ts-gems';
|
|
@@ -21,7 +23,7 @@ interface Row {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
type Result = StrictPick<Row, 'a' | 'c'>;
|
|
24
|
-
// { a?: number } -
|
|
26
|
+
// { a?: number; c: never } - both named keys are kept
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
## `PickFunctions<T>`
|
package/docs/api.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
docs-baseline
|
|
3
|
-
git-commit:
|
|
4
|
-
package-version: 4.0.
|
|
3
|
+
git-commit: 27bbe999f45fa24fe4e1d7d32d5639defa285bdc
|
|
4
|
+
package-version: 4.0.1
|
|
5
5
|
date: 2026-09-09
|
|
6
6
|
verified-against: lib/
|
|
7
|
-
diff-command: git diff
|
|
7
|
+
diff-command: git diff 27bbe999f45fa24fe4e1d7d32d5639defa285bdc..HEAD -- lib/
|
|
8
8
|
-->
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
@@ -98,6 +98,19 @@ type ReadonlyConfig = DeeperReadonly<Config>;
|
|
|
98
98
|
// }
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
A **nullable** object or array property (`SomeObject | null`) still gets
|
|
102
|
+
recursed into — `null` is a leaf on its own, but it is preserved as a
|
|
103
|
+
separate union member alongside the transformed object/array, not lost:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
type Config = {
|
|
107
|
+
server: { host: string } | null;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
type ReadonlyConfig = DeeperReadonly<Config>;
|
|
111
|
+
// { readonly server: { readonly host: string } | null }
|
|
112
|
+
```
|
|
113
|
+
|
|
101
114
|
## Naming patterns used across pages
|
|
102
115
|
|
|
103
116
|
- **`Pick*` / `Omit*`** — select or remove properties matching some criterion
|
package/lib/mutable.d.ts
CHANGED
|
@@ -30,8 +30,8 @@ export type DeepMutable<T> = {
|
|
|
30
30
|
K in keyof T as IfNever<Exclude<T[K], undefined>, never, K>
|
|
31
31
|
]: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
32
32
|
? T[K]
|
|
33
|
-
: // Deep process objects
|
|
34
|
-
DeepMutable<
|
|
33
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
34
|
+
DeepMutable<Exclude<T[K], undefined>>;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -43,12 +43,14 @@ export type DeeperMutable<T> = {
|
|
|
43
43
|
]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
|
|
44
44
|
? T[K]
|
|
45
45
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
46
|
-
?
|
|
46
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
47
|
+
? DeeperMutable<U>[] | null
|
|
48
|
+
: DeeperMutable<U>[]
|
|
47
49
|
: // Do not deep process No-Deep values
|
|
48
|
-
IfNoDeepValue<
|
|
50
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
49
51
|
? T[K]
|
|
50
|
-
: // Deep process objects
|
|
51
|
-
DeeperMutable<
|
|
52
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
53
|
+
DeeperMutable<Exclude<T[K], undefined>>;
|
|
52
54
|
};
|
|
53
55
|
|
|
54
56
|
/**
|
package/lib/omit-never.d.ts
CHANGED
|
@@ -30,11 +30,11 @@ export type OmitNever<T> = {
|
|
|
30
30
|
export type DeepOmitNever<T> = {
|
|
31
31
|
[K in keyof T as IfNever<Exclude<T[K], undefined>, never, K>]: IfNoDeepValue<
|
|
32
32
|
// Do not deep process No-Deep values
|
|
33
|
-
|
|
33
|
+
Exclude<T[K], undefined>
|
|
34
34
|
> extends true
|
|
35
35
|
? T[K]
|
|
36
|
-
: // Deep process objects
|
|
37
|
-
DeepOmitNever<
|
|
36
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
37
|
+
DeepOmitNever<Exclude<T[K], undefined>>;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -49,10 +49,12 @@ export type DeeperOmitNever<T> = {
|
|
|
49
49
|
// Deep process arrays
|
|
50
50
|
T[K]
|
|
51
51
|
> extends readonly (infer U)[]
|
|
52
|
-
?
|
|
52
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
53
|
+
? DeeperOmitNever<U>[] | null
|
|
54
|
+
: DeeperOmitNever<U>[]
|
|
53
55
|
: // Do not deep process No-Deep values
|
|
54
|
-
IfNoDeepValue<
|
|
56
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
55
57
|
? T[K]
|
|
56
|
-
: // Deep process objects
|
|
57
|
-
DeeperOmitNever<
|
|
58
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
59
|
+
DeeperOmitNever<Exclude<T[K], undefined>>;
|
|
58
60
|
};
|
package/lib/omit-undefined.d.ts
CHANGED
|
@@ -30,10 +30,12 @@ export type DeeperOmitUndefined<T> = {
|
|
|
30
30
|
> extends true // Leave fixed-length tuples untouched
|
|
31
31
|
? T[K]
|
|
32
32
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
33
|
-
?
|
|
33
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
34
|
+
? DeeperOmitUndefined<U>[] | null
|
|
35
|
+
: DeeperOmitUndefined<U>[]
|
|
34
36
|
: // Do not deep process No-Deep values
|
|
35
|
-
IfNoDeepValue<
|
|
37
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
36
38
|
? T[K]
|
|
37
|
-
: // Deep process objects
|
|
38
|
-
DeeperOmitUndefined<
|
|
39
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
40
|
+
DeeperOmitUndefined<Exclude<T[K], undefined>>;
|
|
39
41
|
};
|
package/lib/omit.d.ts
CHANGED
|
@@ -7,16 +7,7 @@ import { IfFunction, IfNever, IfTuple } from './type-check.js';
|
|
|
7
7
|
* while preserving strict type checking.
|
|
8
8
|
*/
|
|
9
9
|
export type StrictOmit<T, X extends keyof T> = {
|
|
10
|
-
[
|
|
11
|
-
K in keyof T as Or<
|
|
12
|
-
// Omit never keys
|
|
13
|
-
IfNever<Exclude<T[K], undefined>>,
|
|
14
|
-
// Omit X
|
|
15
|
-
K extends X ? true : false
|
|
16
|
-
> extends true
|
|
17
|
-
? never
|
|
18
|
-
: K
|
|
19
|
-
]: T[K];
|
|
10
|
+
[K in keyof T as K extends X ? never : K]: T[K];
|
|
20
11
|
};
|
|
21
12
|
|
|
22
13
|
/**
|
|
@@ -53,8 +44,8 @@ export type DeepOmitTypes<T, X> = {
|
|
|
53
44
|
K in keyof T as IfNever<Exclude<T[K], undefined | X>, never, K>
|
|
54
45
|
]: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
55
46
|
? Exclude<T[K], X>
|
|
56
|
-
: // Deep process objects
|
|
57
|
-
DeepOmitTypes<
|
|
47
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
48
|
+
DeepOmitTypes<Exclude<T[K], undefined>, X>;
|
|
58
49
|
};
|
|
59
50
|
|
|
60
51
|
/**
|
|
@@ -69,9 +60,11 @@ export type DeeperOmitTypes<T, X> = {
|
|
|
69
60
|
// Deep process arrays // Do not deep process No-Deep values
|
|
70
61
|
T[K]
|
|
71
62
|
> extends readonly (infer U)[]
|
|
72
|
-
?
|
|
73
|
-
|
|
63
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
64
|
+
? DeeperOmitTypes<U, X>[] | null
|
|
65
|
+
: DeeperOmitTypes<U, X>[]
|
|
66
|
+
: IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
74
67
|
? Exclude<T[K], X>
|
|
75
|
-
: // Deep process objects
|
|
76
|
-
DeeperOmitTypes<
|
|
68
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
69
|
+
DeeperOmitTypes<Exclude<T[K], undefined>, X>;
|
|
77
70
|
};
|
package/lib/partial.d.ts
CHANGED
|
@@ -24,8 +24,8 @@ export type DeepPartial<T> = {
|
|
|
24
24
|
Exclude<T[K], undefined>
|
|
25
25
|
> extends true
|
|
26
26
|
? T[K]
|
|
27
|
-
: // Deep process objects
|
|
28
|
-
DeepPartial<
|
|
27
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
28
|
+
DeepPartial<Exclude<T[K], undefined>>;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -37,12 +37,14 @@ export type DeeperPartial<T> = {
|
|
|
37
37
|
> extends true // Leave fixed-length tuples untouched
|
|
38
38
|
? T[K]
|
|
39
39
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
40
|
-
?
|
|
40
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
41
|
+
? DeeperPartial<U>[] | null
|
|
42
|
+
: DeeperPartial<U>[]
|
|
41
43
|
: // Do not deep process No-Deep values
|
|
42
|
-
IfNoDeepValue<
|
|
44
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
43
45
|
? T[K]
|
|
44
|
-
: // Deep process objects
|
|
45
|
-
DeeperPartial<
|
|
46
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
47
|
+
DeeperPartial<Exclude<T[K], undefined>>;
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
/**
|
package/lib/pick.d.ts
CHANGED
|
@@ -13,16 +13,7 @@ import {
|
|
|
13
13
|
* while preserving strict type checking.
|
|
14
14
|
*/
|
|
15
15
|
export type StrictPick<T, X extends keyof T> = {
|
|
16
|
-
[
|
|
17
|
-
K in keyof T as Or<
|
|
18
|
-
// Omit never keys
|
|
19
|
-
IfNever<Exclude<T[K], undefined>>,
|
|
20
|
-
// Omit X
|
|
21
|
-
K extends X ? false : true
|
|
22
|
-
> extends true
|
|
23
|
-
? never
|
|
24
|
-
: K
|
|
25
|
-
]: T[K];
|
|
16
|
+
[K in keyof T as K extends X ? K : never]: T[K];
|
|
26
17
|
};
|
|
27
18
|
|
|
28
19
|
/**
|
package/lib/readonly.d.ts
CHANGED
|
@@ -29,7 +29,9 @@ export type DeeperReadonly<T> = {
|
|
|
29
29
|
]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
|
|
30
30
|
? T[K]
|
|
31
31
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
32
|
-
?
|
|
32
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
33
|
+
? DeeperReadonly<U>[] | null
|
|
34
|
+
: DeeperReadonly<U>[]
|
|
33
35
|
: // Do not deep process No-Deep values
|
|
34
36
|
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
35
37
|
? T[K]
|
|
@@ -87,10 +89,10 @@ export type DeepPickReadonly<T> = {
|
|
|
87
89
|
> extends true
|
|
88
90
|
? never
|
|
89
91
|
: K
|
|
90
|
-
]: IfNoDeepValue<
|
|
92
|
+
]: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
91
93
|
? T[K]
|
|
92
|
-
: // Deep process objects
|
|
93
|
-
DeepPickReadonly<
|
|
94
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
95
|
+
DeepPickReadonly<Exclude<T[K], undefined>>;
|
|
94
96
|
};
|
|
95
97
|
|
|
96
98
|
/**
|
|
@@ -106,10 +108,10 @@ export type DeepOmitReadonly<T> = {
|
|
|
106
108
|
> extends true
|
|
107
109
|
? never
|
|
108
110
|
: K
|
|
109
|
-
]: IfNoDeepValue<
|
|
111
|
+
]: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
110
112
|
? T[K]
|
|
111
|
-
: // Deep process objects
|
|
112
|
-
DeepOmitReadonly<
|
|
113
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
114
|
+
DeepOmitReadonly<Exclude<T[K], undefined>>;
|
|
113
115
|
};
|
|
114
116
|
|
|
115
117
|
/**
|
|
@@ -128,12 +130,14 @@ export type DeeperPickReadonly<T> = {
|
|
|
128
130
|
]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
|
|
129
131
|
? T[K]
|
|
130
132
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
131
|
-
?
|
|
133
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
134
|
+
? DeeperPickReadonly<U>[] | null
|
|
135
|
+
: DeeperPickReadonly<U>[]
|
|
132
136
|
: // Do not deep process No-Deep values
|
|
133
|
-
IfNoDeepValue<
|
|
137
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
134
138
|
? T[K]
|
|
135
|
-
: // Deep process objects
|
|
136
|
-
DeeperPickReadonly<
|
|
139
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
140
|
+
DeeperPickReadonly<Exclude<T[K], undefined>>;
|
|
137
141
|
};
|
|
138
142
|
|
|
139
143
|
/**
|
|
@@ -152,10 +156,12 @@ export type DeeperOmitReadonly<T> = {
|
|
|
152
156
|
]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
|
|
153
157
|
? T[K]
|
|
154
158
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
155
|
-
?
|
|
159
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
160
|
+
? DeeperOmitReadonly<U>[] | null
|
|
161
|
+
: DeeperOmitReadonly<U>[]
|
|
156
162
|
: // Do not deep process No-Deep values
|
|
157
|
-
IfNoDeepValue<
|
|
163
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
158
164
|
? T[K]
|
|
159
|
-
: // Deep process objects
|
|
160
|
-
DeeperOmitReadonly<
|
|
165
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
166
|
+
DeeperOmitReadonly<Exclude<T[K], undefined>>;
|
|
161
167
|
};
|
package/lib/required.d.ts
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { IfNoDeepValue } from './helpers.js';
|
|
2
2
|
import { Or } from './logical.js';
|
|
3
|
-
import { OmitTypes } from './omit.js';
|
|
4
3
|
import { IfEquals, IfNever, IfTuple } from './type-check.js';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Marks given keys as required
|
|
8
7
|
*/
|
|
9
|
-
export type RequiredSome<T, K extends keyof T> =
|
|
10
|
-
Required<Pick<T, K>>,
|
|
11
|
-
null
|
|
12
|
-
> &
|
|
8
|
+
export type RequiredSome<T, K extends keyof T> = Required<Pick<T, K>> &
|
|
13
9
|
Omit<T, K>;
|
|
14
10
|
|
|
15
11
|
/**
|
|
@@ -20,8 +16,8 @@ export type DeepRequired<T> = {
|
|
|
20
16
|
K in keyof T as IfNever<Exclude<T[K], undefined>, never, K>
|
|
21
17
|
]-?: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
22
18
|
? Exclude<T[K], undefined>
|
|
23
|
-
: // Deep process objects
|
|
24
|
-
DeepRequired<
|
|
19
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
20
|
+
DeepRequired<Exclude<T[K], undefined>>;
|
|
25
21
|
};
|
|
26
22
|
|
|
27
23
|
/**
|
|
@@ -33,12 +29,14 @@ export type DeeperRequired<T> = {
|
|
|
33
29
|
> extends true // Leave fixed-length tuples untouched
|
|
34
30
|
? Exclude<T[K], undefined>
|
|
35
31
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
36
|
-
?
|
|
32
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
33
|
+
? DeeperRequired<U>[] | null
|
|
34
|
+
: DeeperRequired<U>[]
|
|
37
35
|
: // Do not deep process No-Deep values
|
|
38
|
-
IfNoDeepValue<
|
|
36
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
39
37
|
? Exclude<T[K], undefined>
|
|
40
|
-
: // Deep process objects
|
|
41
|
-
DeeperRequired<
|
|
38
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
39
|
+
DeeperRequired<Exclude<T[K], undefined>>;
|
|
42
40
|
};
|
|
43
41
|
|
|
44
42
|
/**
|
|
@@ -92,10 +90,10 @@ export type DeepPickRequired<T> = {
|
|
|
92
90
|
> extends true
|
|
93
91
|
? never
|
|
94
92
|
: K
|
|
95
|
-
]: IfNoDeepValue<
|
|
93
|
+
]: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
96
94
|
? T[K]
|
|
97
|
-
: // Deep process objects
|
|
98
|
-
DeepPickRequired<
|
|
95
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
96
|
+
DeepPickRequired<Exclude<T[K], undefined>>;
|
|
99
97
|
};
|
|
100
98
|
|
|
101
99
|
/**
|
|
@@ -111,10 +109,10 @@ export type DeepOmitRequired<T> = {
|
|
|
111
109
|
> extends true
|
|
112
110
|
? never
|
|
113
111
|
: K
|
|
114
|
-
]?: IfNoDeepValue<
|
|
112
|
+
]?: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
|
|
115
113
|
? T[K]
|
|
116
|
-
: // Deep process objects
|
|
117
|
-
DeepOmitRequired<
|
|
114
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
115
|
+
DeepOmitRequired<Exclude<T[K], undefined>>;
|
|
118
116
|
};
|
|
119
117
|
|
|
120
118
|
/**
|
|
@@ -133,12 +131,14 @@ export type DeeperPickRequired<T> = {
|
|
|
133
131
|
]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
|
|
134
132
|
? T[K]
|
|
135
133
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
136
|
-
?
|
|
134
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
135
|
+
? DeeperPickRequired<U>[] | null
|
|
136
|
+
: DeeperPickRequired<U>[]
|
|
137
137
|
: // Do not deep process No-Deep values
|
|
138
|
-
IfNoDeepValue<
|
|
138
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
139
139
|
? T[K]
|
|
140
|
-
: // Deep process objects
|
|
141
|
-
DeeperPickRequired<
|
|
140
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
141
|
+
DeeperPickRequired<Exclude<T[K], undefined>>;
|
|
142
142
|
};
|
|
143
143
|
|
|
144
144
|
/**
|
|
@@ -157,10 +157,12 @@ export type DeeperOmitRequired<T> = {
|
|
|
157
157
|
]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
|
|
158
158
|
? T[K]
|
|
159
159
|
: NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
|
|
160
|
-
?
|
|
160
|
+
? null extends T[K] // Preserve a `| null` member lost by NonNullable above
|
|
161
|
+
? DeeperOmitRequired<U>[] | null
|
|
162
|
+
: DeeperOmitRequired<U>[]
|
|
161
163
|
: // Do not deep process No-Deep values
|
|
162
|
-
IfNoDeepValue<
|
|
164
|
+
IfNoDeepValue<Exclude<T[K], undefined>> extends true
|
|
163
165
|
? T[K]
|
|
164
|
-
: // Deep process objects
|
|
165
|
-
DeeperOmitRequired<
|
|
166
|
+
: // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
|
|
167
|
+
DeeperOmitRequired<Exclude<T[K], undefined>>;
|
|
166
168
|
};
|
package/lib/type-check.d.ts
CHANGED
|
@@ -127,6 +127,14 @@ export type IfClassOrAny<T, Y = true, N = false> =
|
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
129
|
* Returns "Y" if "T1" is exactly same with "T2", "N" otherwise
|
|
130
|
+
*
|
|
131
|
+
* The `IfObject<T1> | IfObject<T2>` check below looks like it should be
|
|
132
|
+
* `Or<IfObject<T1>, IfObject<T2>>` (this file's usual pattern), but it is
|
|
133
|
+
* not a bug: it deliberately only takes the EqualsWrapped/object-safe path
|
|
134
|
+
* when BOTH sides are objects. Wrapping a non-object side (e.g. `string`)
|
|
135
|
+
* in `EqualsWrapped` maps over its own keys instead of comparing it as
|
|
136
|
+
* itself, which gives wrong answers - switching this to `Or` breaks
|
|
137
|
+
* multiple cases in test/type-check.spec.ts's `IfEquals` suite.
|
|
130
138
|
*/
|
|
131
139
|
export type IfEquals<T1, T2, Y = true, N = false> =
|
|
132
140
|
IfObject<T1> | IfObject<T2> extends true
|