ts-gems 3.12.0 → 4.0.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/lib/required.d.ts CHANGED
@@ -1,44 +1,42 @@
1
1
  import { IfNoDeepValue } from './helpers.js';
2
2
  import { Or } from './logical.js';
3
- import { OmitTypes } from './omit.js';
4
- import { IfEquals, IfNever } from './type-check.js';
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> = OmitTypes<
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
  /**
16
12
  * Make all properties in T required deeply
17
13
  */
18
14
  export type DeepRequired<T> = {
19
- [K in keyof T as IfNever<
20
- Exclude<T[K], undefined>,
21
- never,
22
- K
23
- >]-?: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
15
+ [
16
+ K in keyof T as IfNever<Exclude<T[K], undefined>, never, K>
17
+ ]-?: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
24
18
  ? Exclude<T[K], undefined>
25
- : // Deep process objects
26
- DeepRequired<NonNullable<T[K]>>;
19
+ : // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
20
+ DeepRequired<Exclude<T[K], undefined>>;
27
21
  };
28
22
 
29
23
  /**
30
24
  * Make all properties in T required deeply including arrays
31
25
  */
32
26
  export type DeeperRequired<T> = {
33
- [K in keyof T as IfNever<Exclude<T[K], undefined>, never, K>]-?: NonNullable<
34
- T[K]
35
- > extends (infer U)[] // Deep process arrays
36
- ? DeeperRequired<U>[]
37
- : // Do not deep process No-Deep values
38
- IfNoDeepValue<NonNullable<T[K]>> extends true
39
- ? Exclude<T[K], undefined>
40
- : // Deep process objects
41
- DeepRequired<NonNullable<T[K]>>;
27
+ [K in keyof T as IfNever<Exclude<T[K], undefined>, never, K>]-?: IfTuple<
28
+ NonNullable<T[K]>
29
+ > extends true // Leave fixed-length tuples untouched
30
+ ? Exclude<T[K], undefined>
31
+ : NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
32
+ ? null extends T[K] // Preserve a `| null` member lost by NonNullable above
33
+ ? DeeperRequired<U>[] | null
34
+ : DeeperRequired<U>[]
35
+ : // Do not deep process No-Deep values
36
+ IfNoDeepValue<Exclude<T[K], undefined>> extends true
37
+ ? Exclude<T[K], undefined>
38
+ : // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
39
+ DeeperRequired<Exclude<T[K], undefined>>;
42
40
  };
43
41
 
44
42
  /**
@@ -51,100 +49,120 @@ export type RequiredKeys<T> = keyof PickRequired<T>;
51
49
  * Pick all required properties in T
52
50
  */
53
51
  export type PickRequired<T> = {
54
- [K in keyof T as Or<
55
- // Omit never keys
56
- IfNever<Exclude<T[K], undefined>>,
57
- // Omit optional
58
- IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }>
59
- > extends true
60
- ? never
61
- : K]: T[K];
52
+ [
53
+ K in keyof T as Or<
54
+ // Omit never keys
55
+ IfNever<Exclude<T[K], undefined>>,
56
+ // Omit optional
57
+ IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }>
58
+ > extends true
59
+ ? never
60
+ : K
61
+ ]: T[K];
62
62
  };
63
63
 
64
64
  /**
65
65
  * Pick all required properties in T
66
66
  */
67
67
  export type OmitRequired<T> = {
68
- [K in keyof T as Or<
69
- // Omit never keys
70
- IfNever<Exclude<T[K], undefined>>,
71
- // Omit optional
72
- IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }, false, true>
73
- > extends true
74
- ? never
75
- : K]: T[K];
68
+ [
69
+ K in keyof T as Or<
70
+ // Omit never keys
71
+ IfNever<Exclude<T[K], undefined>>,
72
+ // Omit optional
73
+ IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }, false, true>
74
+ > extends true
75
+ ? never
76
+ : K
77
+ ]: T[K];
76
78
  };
77
79
 
78
80
  /**
79
81
  * Pick all required properties in T deeply
80
82
  */
81
83
  export type DeepPickRequired<T> = {
82
- [K in keyof T as Or<
83
- // Omit never keys
84
- IfNever<Exclude<T[K], undefined>>,
85
- // Omit optional
86
- IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }>
87
- > extends true
88
- ? never
89
- : K]: IfNoDeepValue<NonNullable<T[K]>> extends true // Do not deep process No-Deep values
84
+ [
85
+ K in keyof T as Or<
86
+ // Omit never keys
87
+ IfNever<Exclude<T[K], undefined>>,
88
+ // Omit optional
89
+ IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }>
90
+ > extends true
91
+ ? never
92
+ : K
93
+ ]: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
90
94
  ? T[K]
91
- : // Deep process objects
92
- DeepPickRequired<NonNullable<T[K]>>;
95
+ : // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
96
+ DeepPickRequired<Exclude<T[K], undefined>>;
93
97
  };
94
98
 
95
99
  /**
96
100
  * Omit all required properties in T deeply
97
101
  */
98
102
  export type DeepOmitRequired<T> = {
99
- [K in keyof T as Or<
100
- // Omit never keys
101
- IfNever<Exclude<T[K], undefined>>,
102
- // Omit required
103
- IfEquals<{ [Q in K]: T[K] }, { [Q in K]-?: T[K] }>
104
- > extends true
105
- ? never
106
- : K]?: IfNoDeepValue<NonNullable<T[K]>> extends true // Do not deep process No-Deep values
103
+ [
104
+ K in keyof T as Or<
105
+ // Omit never keys
106
+ IfNever<Exclude<T[K], undefined>>,
107
+ // Omit required
108
+ IfEquals<{ [Q in K]: T[K] }, { [Q in K]-?: T[K] }>
109
+ > extends true
110
+ ? never
111
+ : K
112
+ ]?: IfNoDeepValue<Exclude<T[K], undefined>> extends true // Do not deep process No-Deep values
107
113
  ? T[K]
108
- : // Deep process objects
109
- DeepOmitRequired<NonNullable<T[K]>>;
114
+ : // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
115
+ DeepOmitRequired<Exclude<T[K], undefined>>;
110
116
  };
111
117
 
112
118
  /**
113
119
  * Pick all required properties in T deeply including arrays
114
120
  */
115
121
  export type DeeperPickRequired<T> = {
116
- [K in keyof T as Or<
117
- // Omit never keys
118
- IfNever<Exclude<T[K], undefined>>,
119
- // Omit required
120
- IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }>
121
- > extends true
122
- ? never
123
- : K]: NonNullable<T[K]> extends (infer U)[] // Deep process arrays
124
- ? DeeperPickRequired<U>[]
125
- : // Do not deep process No-Deep values
126
- IfNoDeepValue<NonNullable<T[K]>> extends true
127
- ? T[K]
128
- : // Deep process objects
129
- DeeperPickRequired<NonNullable<T[K]>>;
122
+ [
123
+ K in keyof T as Or<
124
+ // Omit never keys
125
+ IfNever<Exclude<T[K], undefined>>,
126
+ // Omit required
127
+ IfEquals<{ [Q in K]: T[K] }, { [Q in K]?: T[K] }>
128
+ > extends true
129
+ ? never
130
+ : K
131
+ ]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
132
+ ? T[K]
133
+ : NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
134
+ ? null extends T[K] // Preserve a `| null` member lost by NonNullable above
135
+ ? DeeperPickRequired<U>[] | null
136
+ : DeeperPickRequired<U>[]
137
+ : // Do not deep process No-Deep values
138
+ IfNoDeepValue<Exclude<T[K], undefined>> extends true
139
+ ? T[K]
140
+ : // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
141
+ DeeperPickRequired<Exclude<T[K], undefined>>;
130
142
  };
131
143
 
132
144
  /**
133
145
  * Omit all required properties in T deeply including arrays
134
146
  */
135
147
  export type DeeperOmitRequired<T> = {
136
- [K in keyof T as Or<
137
- // Omit never keys
138
- IfNever<Exclude<T[K], undefined>>,
139
- // Omit required
140
- IfEquals<{ [Q in K]: T[K] }, { [Q in K]-?: T[K] }>
141
- > extends true
142
- ? never
143
- : K]: NonNullable<T[K]> extends (infer U)[] // Deep process arrays
144
- ? DeeperOmitRequired<U>[]
145
- : // Do not deep process No-Deep values
146
- IfNoDeepValue<NonNullable<T[K]>> extends true
147
- ? T[K]
148
- : // Deep process objects
149
- DeeperOmitRequired<NonNullable<T[K]>>;
148
+ [
149
+ K in keyof T as Or<
150
+ // Omit never keys
151
+ IfNever<Exclude<T[K], undefined>>,
152
+ // Omit required
153
+ IfEquals<{ [Q in K]: T[K] }, { [Q in K]-?: T[K] }>
154
+ > extends true
155
+ ? never
156
+ : K
157
+ ]: IfTuple<NonNullable<T[K]>> extends true // Leave fixed-length tuples untouched
158
+ ? T[K]
159
+ : NonNullable<T[K]> extends readonly (infer U)[] // Deep process arrays
160
+ ? null extends T[K] // Preserve a `| null` member lost by NonNullable above
161
+ ? DeeperOmitRequired<U>[] | null
162
+ : DeeperOmitRequired<U>[]
163
+ : // Do not deep process No-Deep values
164
+ IfNoDeepValue<Exclude<T[K], undefined>> extends true
165
+ ? T[K]
166
+ : // Deep process objects (Exclude, not NonNullable - preserves a `| null` member)
167
+ DeeperOmitRequired<Exclude<T[K], undefined>>;
150
168
  };
@@ -48,13 +48,15 @@ export type IfNullish<T, Y = true, N = false> =
48
48
  * Returns Y if typeof T is a tuple, N otherwise
49
49
  */
50
50
  export type IfTuple<T, Y = true, N = false> =
51
- IfEquals<T, [any]> extends true
52
- ? T extends [any]
53
- ? number extends T['length']
54
- ? N
55
- : Y
56
- : N
57
- : N;
51
+ IfAny<T> extends true
52
+ ? N
53
+ : IfNever<T> extends true
54
+ ? N
55
+ : T extends readonly unknown[]
56
+ ? number extends T['length']
57
+ ? N
58
+ : Y
59
+ : N;
58
60
  export type IfTupleOrAny<T, Y = true, N = false> =
59
61
  IfAny<T> extends true ? Y : IfTuple<T, Y, N>;
60
62
 
@@ -125,10 +127,17 @@ export type IfClassOrAny<T, Y = true, N = false> =
125
127
 
126
128
  /**
127
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.
128
138
  */
129
139
  export type IfEquals<T1, T2, Y = true, N = false> =
130
- | IfObject<T1>
131
- | IfObject<T2> extends true
140
+ IfObject<T1> | IfObject<T2> extends true
132
141
  ? (<G>() => G extends EqualsWrapped<T1> ? 1 : 2) extends <
133
142
  G,
134
143
  >() => G extends EqualsWrapped<T2> ? 1 : 2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ts-gems",
3
3
  "description": "Valuable typing extensions for TypeScript",
4
- "version": "3.12.0",
4
+ "version": "4.0.1",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "module": "./lib/index.js",
@@ -17,29 +17,31 @@
17
17
  "lint": "eslint . --max-warnings=0",
18
18
  "lint:fix": "eslint . --max-warnings=0 --fix",
19
19
  "format": "prettier . --write --log-level=warn",
20
- "test": "npm run test:common && npm run test:nostrict",
20
+ "test": "tsc -b tsconfig.json && npm run test:common && npm run test:nostrict",
21
21
  "test:common": "mocha",
22
- "test:nostrict": "TS_NODE_PROJECT=\"tsconfig.json\" && mocha"
22
+ "test:nostrict": "TS_NODE_PROJECT=\"tsconfig.json\" && mocha",
23
+ "graph": "graphify upate ."
23
24
  },
24
25
  "devDependencies": {
25
- "@panates/eslint-config": "^2.1.3",
26
- "@panates/eslint-config-ts": "^2.1.3",
27
- "@panates/tsconfig": "^2.1.3",
28
- "@swc/core": "^1.15.32",
29
- "@swc/helpers": "^0.5.21",
30
- "@swc-node/register": "^1.11.1",
26
+ "@panates/eslint-config": "^2.1.6",
27
+ "@panates/eslint-config-ts": "^2.1.6",
28
+ "@panates/tsconfig": "^2.1.6",
29
+ "@swc/core": "^1.16.2",
30
+ "@swc/helpers": "^0.5.23",
31
+ "@swc-node/register": "^1.12.1",
31
32
  "@types/mocha": "^10.0.10",
32
- "@types/node": "^25.6.0",
33
- "c8": "^11.0.0",
34
- "globals": "^17.5.0",
33
+ "@types/node": "^26.5.0",
34
+ "c8": "^12.0.0",
35
+ "globals": "^17.12.0",
35
36
  "husky": "^9.1.7",
36
- "mocha": "^11.7.5",
37
- "prettier": "^3.8.3",
38
- "typescript": "^6.0.3"
37
+ "mocha": "^12.0.0",
38
+ "prettier": "^3.9.6",
39
+ "typescript": "6.0.3"
39
40
  },
40
41
  "files": [
41
42
  "LICENSE",
42
43
  "README",
44
+ "docs/",
43
45
  "lib/"
44
46
  ],
45
47
  "keywords": [