ts-data-forge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +534 -0
  3. package/package.json +101 -0
  4. package/src/array/array-utils-creation.test.mts +443 -0
  5. package/src/array/array-utils-modification.test.mts +197 -0
  6. package/src/array/array-utils-overload-type-error.test.mts +149 -0
  7. package/src/array/array-utils-reducing-value.test.mts +425 -0
  8. package/src/array/array-utils-search.test.mts +169 -0
  9. package/src/array/array-utils-set-op.test.mts +335 -0
  10. package/src/array/array-utils-slice-clamped.test.mts +113 -0
  11. package/src/array/array-utils-slicing.test.mts +316 -0
  12. package/src/array/array-utils-transformation.test.mts +790 -0
  13. package/src/array/array-utils-validation.test.mts +492 -0
  14. package/src/array/array-utils.mts +4000 -0
  15. package/src/array/array.test.mts +146 -0
  16. package/src/array/index.mts +2 -0
  17. package/src/array/tuple-utils.mts +519 -0
  18. package/src/array/tuple-utils.test.mts +518 -0
  19. package/src/collections/imap-mapped.mts +801 -0
  20. package/src/collections/imap-mapped.test.mts +860 -0
  21. package/src/collections/imap.mts +651 -0
  22. package/src/collections/imap.test.mts +932 -0
  23. package/src/collections/index.mts +6 -0
  24. package/src/collections/iset-mapped.mts +889 -0
  25. package/src/collections/iset-mapped.test.mts +1187 -0
  26. package/src/collections/iset.mts +682 -0
  27. package/src/collections/iset.test.mts +1084 -0
  28. package/src/collections/queue.mts +390 -0
  29. package/src/collections/queue.test.mts +282 -0
  30. package/src/collections/stack.mts +423 -0
  31. package/src/collections/stack.test.mts +225 -0
  32. package/src/expect-type.mts +206 -0
  33. package/src/functional/index.mts +4 -0
  34. package/src/functional/match.mts +300 -0
  35. package/src/functional/match.test.mts +177 -0
  36. package/src/functional/optional.mts +733 -0
  37. package/src/functional/optional.test.mts +619 -0
  38. package/src/functional/pipe.mts +212 -0
  39. package/src/functional/pipe.test.mts +85 -0
  40. package/src/functional/result.mts +1134 -0
  41. package/src/functional/result.test.mts +777 -0
  42. package/src/globals.d.mts +38 -0
  43. package/src/guard/has-key.mts +119 -0
  44. package/src/guard/has-key.test.mts +219 -0
  45. package/src/guard/index.mts +7 -0
  46. package/src/guard/is-non-empty-string.mts +108 -0
  47. package/src/guard/is-non-empty-string.test.mts +91 -0
  48. package/src/guard/is-non-null-object.mts +106 -0
  49. package/src/guard/is-non-null-object.test.mts +90 -0
  50. package/src/guard/is-primitive.mts +165 -0
  51. package/src/guard/is-primitive.test.mts +102 -0
  52. package/src/guard/is-record.mts +153 -0
  53. package/src/guard/is-record.test.mts +112 -0
  54. package/src/guard/is-type.mts +450 -0
  55. package/src/guard/is-type.test.mts +496 -0
  56. package/src/guard/key-is-in.mts +163 -0
  57. package/src/guard/key-is-in.test.mts +19 -0
  58. package/src/index.mts +10 -0
  59. package/src/iterator/index.mts +1 -0
  60. package/src/iterator/range.mts +120 -0
  61. package/src/iterator/range.test.mts +33 -0
  62. package/src/json/index.mts +1 -0
  63. package/src/json/json.mts +711 -0
  64. package/src/json/json.test.mts +628 -0
  65. package/src/number/branded-types/finite-number.mts +354 -0
  66. package/src/number/branded-types/finite-number.test.mts +135 -0
  67. package/src/number/branded-types/index.mts +26 -0
  68. package/src/number/branded-types/int.mts +278 -0
  69. package/src/number/branded-types/int.test.mts +140 -0
  70. package/src/number/branded-types/int16.mts +192 -0
  71. package/src/number/branded-types/int16.test.mts +170 -0
  72. package/src/number/branded-types/int32.mts +193 -0
  73. package/src/number/branded-types/int32.test.mts +170 -0
  74. package/src/number/branded-types/non-negative-finite-number.mts +223 -0
  75. package/src/number/branded-types/non-negative-finite-number.test.mts +188 -0
  76. package/src/number/branded-types/non-negative-int16.mts +187 -0
  77. package/src/number/branded-types/non-negative-int16.test.mts +201 -0
  78. package/src/number/branded-types/non-negative-int32.mts +187 -0
  79. package/src/number/branded-types/non-negative-int32.test.mts +204 -0
  80. package/src/number/branded-types/non-zero-finite-number.mts +229 -0
  81. package/src/number/branded-types/non-zero-finite-number.test.mts +198 -0
  82. package/src/number/branded-types/non-zero-int.mts +167 -0
  83. package/src/number/branded-types/non-zero-int.test.mts +177 -0
  84. package/src/number/branded-types/non-zero-int16.mts +196 -0
  85. package/src/number/branded-types/non-zero-int16.test.mts +195 -0
  86. package/src/number/branded-types/non-zero-int32.mts +196 -0
  87. package/src/number/branded-types/non-zero-int32.test.mts +197 -0
  88. package/src/number/branded-types/non-zero-safe-int.mts +196 -0
  89. package/src/number/branded-types/non-zero-safe-int.test.mts +232 -0
  90. package/src/number/branded-types/non-zero-uint16.mts +189 -0
  91. package/src/number/branded-types/non-zero-uint16.test.mts +199 -0
  92. package/src/number/branded-types/non-zero-uint32.mts +189 -0
  93. package/src/number/branded-types/non-zero-uint32.test.mts +199 -0
  94. package/src/number/branded-types/positive-finite-number.mts +241 -0
  95. package/src/number/branded-types/positive-finite-number.test.mts +204 -0
  96. package/src/number/branded-types/positive-int.mts +304 -0
  97. package/src/number/branded-types/positive-int.test.mts +176 -0
  98. package/src/number/branded-types/positive-int16.mts +188 -0
  99. package/src/number/branded-types/positive-int16.test.mts +197 -0
  100. package/src/number/branded-types/positive-int32.mts +188 -0
  101. package/src/number/branded-types/positive-int32.test.mts +197 -0
  102. package/src/number/branded-types/positive-safe-int.mts +187 -0
  103. package/src/number/branded-types/positive-safe-int.test.mts +210 -0
  104. package/src/number/branded-types/positive-uint16.mts +188 -0
  105. package/src/number/branded-types/positive-uint16.test.mts +203 -0
  106. package/src/number/branded-types/positive-uint32.mts +188 -0
  107. package/src/number/branded-types/positive-uint32.test.mts +203 -0
  108. package/src/number/branded-types/safe-int.mts +291 -0
  109. package/src/number/branded-types/safe-int.test.mts +170 -0
  110. package/src/number/branded-types/safe-uint.mts +187 -0
  111. package/src/number/branded-types/safe-uint.test.mts +176 -0
  112. package/src/number/branded-types/uint.mts +179 -0
  113. package/src/number/branded-types/uint.test.mts +158 -0
  114. package/src/number/branded-types/uint16.mts +186 -0
  115. package/src/number/branded-types/uint16.test.mts +170 -0
  116. package/src/number/branded-types/uint32.mts +218 -0
  117. package/src/number/branded-types/uint32.test.mts +170 -0
  118. package/src/number/enum/index.mts +2 -0
  119. package/src/number/enum/int8.mts +344 -0
  120. package/src/number/enum/int8.test.mts +180 -0
  121. package/src/number/enum/uint8.mts +293 -0
  122. package/src/number/enum/uint8.test.mts +164 -0
  123. package/src/number/index.mts +4 -0
  124. package/src/number/num.mts +604 -0
  125. package/src/number/num.test.mts +242 -0
  126. package/src/number/refined-number-utils.mts +566 -0
  127. package/src/object/index.mts +1 -0
  128. package/src/object/object.mts +447 -0
  129. package/src/object/object.test.mts +124 -0
  130. package/src/others/cast-mutable.mts +113 -0
  131. package/src/others/cast-readonly.mts +192 -0
  132. package/src/others/cast-readonly.test.mts +89 -0
  133. package/src/others/if-then.mts +98 -0
  134. package/src/others/if-then.test.mts +75 -0
  135. package/src/others/index.mts +7 -0
  136. package/src/others/map-nullable.mts +172 -0
  137. package/src/others/map-nullable.test.mts +297 -0
  138. package/src/others/memoize-function.mts +196 -0
  139. package/src/others/memoize-function.test.mts +168 -0
  140. package/src/others/tuple.mts +160 -0
  141. package/src/others/tuple.test.mts +11 -0
  142. package/src/others/unknown-to-string.mts +215 -0
  143. package/src/others/unknown-to-string.test.mts +114 -0
@@ -0,0 +1,450 @@
1
+ /**
2
+ * Type guard that checks if a value is `undefined`.
3
+ *
4
+ * **Type Narrowing Behavior:**
5
+ * - Narrows the input type to `undefined` when `true`
6
+ * - Useful for explicit undefined checks
7
+ *
8
+ * @param u - The value to check
9
+ * @returns `true` if `u` is `undefined`, `false` otherwise.
10
+ * When `true`, TypeScript narrows the type to `undefined`.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const value: string | undefined = getValue();
15
+ *
16
+ * if (isUndefined(value)) {
17
+ * // value is now typed as undefined
18
+ * console.log('Value is undefined');
19
+ * } else {
20
+ * // value is now typed as string
21
+ * console.log('Value length:', value.length);
22
+ * }
23
+ * ```
24
+ */
25
+ export const isUndefined = (u: unknown): u is undefined => u === undefined;
26
+
27
+ /**
28
+ * Type guard that checks if a value is not `undefined`.
29
+ *
30
+ * **Type Narrowing Behavior:**
31
+ * - Excludes `undefined` from the input type when `true`
32
+ * - Preserves all other types in the union
33
+ * - Commonly used to filter out undefined values
34
+ *
35
+ * @template T - The type of the input value
36
+ * @param u - The value to check
37
+ * @returns `true` if `u` is not `undefined`, `false` otherwise.
38
+ * When `true`, TypeScript excludes `undefined` from the type.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const items: (string | undefined)[] = ['a', undefined, 'b', undefined, 'c'];
43
+ *
44
+ * const definedItems = items.filter(isNotUndefined);
45
+ * // definedItems is now string[] - undefined values are filtered out
46
+ *
47
+ * definedItems.forEach(item => {
48
+ * // item is guaranteed to be string, not undefined
49
+ * console.log(item.toUpperCase());
50
+ * });
51
+ * ```
52
+ */
53
+ export const isNotUndefined = <T,>(u: T): u is RelaxedExclude<T, undefined> =>
54
+ u !== undefined;
55
+
56
+ /**
57
+ * Type guard that checks if a value is a boolean.
58
+ *
59
+ * **Type Narrowing Behavior:**
60
+ * - Narrows `unknown` to `boolean` when `true`
61
+ * - Preserves literal boolean types (`true | false`)
62
+ *
63
+ * @param u - The value to check
64
+ * @returns `true` if `u` is a boolean, `false` otherwise.
65
+ * When `true`, TypeScript narrows the type to `boolean`.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const userInput: unknown = parseInput();
70
+ *
71
+ * if (isBoolean(userInput)) {
72
+ * // userInput is now typed as boolean
73
+ * console.log('Boolean value:', userInput ? 'true' : 'false');
74
+ * }
75
+ * ```
76
+ */
77
+ export const isBoolean = (u: unknown): u is boolean => typeof u === 'boolean';
78
+
79
+ /**
80
+ * Type guard that checks if a value is not a boolean.
81
+ *
82
+ * **Type Narrowing Behavior:**
83
+ * - Excludes `boolean` from the input type when `true`
84
+ * - Preserves all other types in the union
85
+ *
86
+ * @template T - The type of the input value
87
+ * @param u - The value to check
88
+ * @returns `true` if `u` is not a boolean, `false` otherwise.
89
+ * When `true`, TypeScript excludes `boolean` from the type.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * type MixedValue = string | number | boolean;
94
+ * const value: MixedValue = getValue();
95
+ *
96
+ * if (isNotBoolean(value)) {
97
+ * // value is now string | number
98
+ * console.log('Non-boolean value:', value);
99
+ * }
100
+ * ```
101
+ */
102
+ export const isNotBoolean = <T,>(u: T): u is RelaxedExclude<T, boolean> =>
103
+ typeof u !== 'boolean';
104
+
105
+ /**
106
+ * Type guard that checks if a value is a number.
107
+ *
108
+ * **Type Narrowing Behavior:**
109
+ * - Narrows `unknown` to `number` when `true`
110
+ * - Includes `NaN`, `Infinity`, and `-Infinity` as valid numbers
111
+ * - Preserves literal number types when possible
112
+ *
113
+ * @param u - The value to check
114
+ * @returns `true` if `u` is a number, `false` otherwise.
115
+ * When `true`, TypeScript narrows the type to `number`.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const userInput: unknown = parseInput();
120
+ *
121
+ * if (isNumber(userInput)) {
122
+ * // userInput is now typed as number
123
+ * console.log('Number value:', userInput.toFixed(2));
124
+ *
125
+ * // Note: this includes NaN and Infinity
126
+ * if (Number.isFinite(userInput)) {
127
+ * console.log('Finite number:', userInput);
128
+ * }
129
+ * }
130
+ * ```
131
+ */
132
+ export const isNumber = (u: unknown): u is number => typeof u === 'number';
133
+
134
+ /**
135
+ * Type guard that checks if a value is not a number.
136
+ *
137
+ * **Type Narrowing Behavior:**
138
+ * - Excludes `number` from the input type when `true`
139
+ * - Preserves all other types in the union
140
+ *
141
+ * @template T - The type of the input value
142
+ * @param u - The value to check
143
+ * @returns `true` if `u` is not a number, `false` otherwise.
144
+ * When `true`, TypeScript excludes `number` from the type.
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * type Value = string | number | boolean;
149
+ * const values: Value[] = ['hello', 42, true, 3.14, false];
150
+ *
151
+ * const nonNumbers = values.filter(isNotNumber);
152
+ * // nonNumbers is now (string | boolean)[] - numbers are filtered out
153
+ * ```
154
+ */
155
+ export const isNotNumber = <T,>(u: T): u is RelaxedExclude<T, number> =>
156
+ typeof u !== 'number';
157
+
158
+ /**
159
+ * Type guard that checks if a value is a bigint.
160
+ *
161
+ * **Type Narrowing Behavior:**
162
+ * - Narrows `unknown` to `bigint` when `true`
163
+ * - Identifies values created with `BigInt()` constructor or `n` suffix
164
+ *
165
+ * @param u - The value to check
166
+ * @returns `true` if `u` is a bigint, `false` otherwise.
167
+ * When `true`, TypeScript narrows the type to `bigint`.
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const userInput: unknown = parseInput();
172
+ *
173
+ * if (isBigint(userInput)) {
174
+ * // userInput is now typed as bigint
175
+ * console.log('BigInt value:', userInput.toString());
176
+ * const doubled = userInput * 2n; // Safe bigint operations
177
+ * }
178
+ * ```
179
+ */
180
+ export const isBigint = (u: unknown): u is bigint => typeof u === 'bigint';
181
+
182
+ /**
183
+ * Type guard that checks if a value is not a bigint.
184
+ *
185
+ * **Type Narrowing Behavior:**
186
+ * - Excludes `bigint` from the input type when `true`
187
+ * - Preserves all other types in the union
188
+ *
189
+ * @template T - The type of the input value
190
+ * @param u - The value to check
191
+ * @returns `true` if `u` is not a bigint, `false` otherwise.
192
+ * When `true`, TypeScript excludes `bigint` from the type.
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * type NumericValue = number | bigint;
197
+ * const value: NumericValue = getValue();
198
+ *
199
+ * if (isNotBigint(value)) {
200
+ * // value is now number
201
+ * console.log('Regular number:', value.toFixed(2));
202
+ * }
203
+ * ```
204
+ */
205
+ export const isNotBigint = <T,>(u: T): u is RelaxedExclude<T, bigint> =>
206
+ typeof u !== 'bigint';
207
+
208
+ /**
209
+ * Type guard that checks if a value is a string.
210
+ *
211
+ * **Type Narrowing Behavior:**
212
+ * - Narrows `unknown` to `string` when `true`
213
+ * - Preserves literal string types when possible
214
+ * - Includes empty strings
215
+ *
216
+ * @param u - The value to check
217
+ * @returns `true` if `u` is a string, `false` otherwise.
218
+ * When `true`, TypeScript narrows the type to `string`.
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const userInput: unknown = parseInput();
223
+ *
224
+ * if (isString(userInput)) {
225
+ * // userInput is now typed as string
226
+ * console.log('String length:', userInput.length);
227
+ * console.log('Uppercase:', userInput.toUpperCase());
228
+ *
229
+ * // You can further check for non-empty strings
230
+ * if (userInput.length > 0) {
231
+ * console.log('Non-empty string:', userInput);
232
+ * }
233
+ * }
234
+ * ```
235
+ */
236
+ export const isString = (u: unknown): u is string => typeof u === 'string';
237
+
238
+ /**
239
+ * Type guard that checks if a value is not a string.
240
+ *
241
+ * **Type Narrowing Behavior:**
242
+ * - Excludes `string` from the input type when `true`
243
+ * - Preserves all other types in the union
244
+ *
245
+ * @template T - The type of the input value
246
+ * @param u - The value to check
247
+ * @returns `true` if `u` is not a string, `false` otherwise.
248
+ * When `true`, TypeScript excludes `string` from the type.
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * type Value = string | number | boolean;
253
+ * const mixedValues: Value[] = ['hello', 42, true, 'world', 3.14];
254
+ *
255
+ * const nonStrings = mixedValues.filter(isNotString);
256
+ * // nonStrings is now (number | boolean)[] - strings are filtered out
257
+ * ```
258
+ */
259
+ export const isNotString = <T,>(u: T): u is RelaxedExclude<T, string> =>
260
+ typeof u !== 'string';
261
+
262
+ /**
263
+ * Type guard that checks if a value is a symbol.
264
+ *
265
+ * **Type Narrowing Behavior:**
266
+ * - Narrows `unknown` to `symbol` when `true`
267
+ * - Identifies values created with `Symbol()` constructor
268
+ *
269
+ * @param u - The value to check
270
+ * @returns `true` if `u` is a symbol, `false` otherwise.
271
+ * When `true`, TypeScript narrows the type to `symbol`.
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * const userInput: unknown = parseInput();
276
+ *
277
+ * if (isSymbol(userInput)) {
278
+ * // userInput is now typed as symbol
279
+ * console.log('Symbol description:', userInput.description);
280
+ * console.log('Symbol string:', userInput.toString());
281
+ * }
282
+ * ```
283
+ */
284
+ export const isSymbol = (u: unknown): u is symbol => typeof u === 'symbol';
285
+
286
+ /**
287
+ * Type guard that checks if a value is not a symbol.
288
+ *
289
+ * **Type Narrowing Behavior:**
290
+ * - Excludes `symbol` from the input type when `true`
291
+ * - Preserves all other types in the union
292
+ *
293
+ * @template T - The type of the input value
294
+ * @param u - The value to check
295
+ * @returns `true` if `u` is not a symbol, `false` otherwise.
296
+ * When `true`, TypeScript excludes `symbol` from the type.
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * type PropertyKey = string | number | symbol;
301
+ * const key: PropertyKey = getPropertyKey();
302
+ *
303
+ * if (isNotSymbol(key)) {
304
+ * // key is now string | number
305
+ * console.log('Non-symbol key:', key);
306
+ * }
307
+ * ```
308
+ */
309
+ export const isNotSymbol = <T,>(u: T): u is RelaxedExclude<T, symbol> =>
310
+ typeof u !== 'symbol';
311
+
312
+ /**
313
+ * Type guard that checks if a value is `null`.
314
+ *
315
+ * **Type Narrowing Behavior:**
316
+ * - Narrows the input type to `null` when `true`
317
+ * - Useful for explicit null checks
318
+ *
319
+ * @param u - The value to check
320
+ * @returns `true` if `u` is `null`, `false` otherwise.
321
+ * When `true`, TypeScript narrows the type to `null`.
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * const value: string | null = getValue();
326
+ *
327
+ * if (isNull(value)) {
328
+ * // value is now typed as null
329
+ * console.log('Value is null');
330
+ * } else {
331
+ * // value is now typed as string
332
+ * console.log('Value length:', value.length);
333
+ * }
334
+ * ```
335
+ */
336
+ export const isNull = (u: unknown): u is null => u === null;
337
+
338
+ /**
339
+ * Type guard that checks if a value is not `null`.
340
+ *
341
+ * **Type Narrowing Behavior:**
342
+ * - Excludes `null` from the input type when `true`
343
+ * - Preserves all other types including `undefined`
344
+ * - Commonly used to filter out null values
345
+ *
346
+ * @template T - The type of the input value (which could be `null`)
347
+ * @param u - The value to check
348
+ * @returns `true` if `u` is not `null`, `false` otherwise.
349
+ * When `true`, TypeScript excludes `null` from the type.
350
+ *
351
+ * @example
352
+ * ```typescript
353
+ * const items: (string | null)[] = ['a', null, 'b', null, 'c'];
354
+ *
355
+ * const nonNullItems = items.filter(isNotNull);
356
+ * // nonNullItems is now string[] - null values are filtered out
357
+ *
358
+ * nonNullItems.forEach(item => {
359
+ * // item is guaranteed to be string, not null
360
+ * console.log(item.toUpperCase());
361
+ * });
362
+ * ```
363
+ */
364
+ export const isNotNull = <T,>(u: T | null): u is T => u !== null;
365
+
366
+ /**
367
+ * Type guard that checks if a value is `null` or `undefined` (nullish).
368
+ *
369
+ * This function uses the loose equality operator (`==`) to check for both `null` and `undefined`
370
+ * in a single comparison, which is the standard JavaScript idiom for nullish checks.
371
+ *
372
+ * **Type Narrowing Behavior:**
373
+ * - Narrows the input type to `null | undefined` when `true`
374
+ * - Useful for checking if a value is "nullish" (either null or undefined)
375
+ *
376
+ * @param u - The value to check
377
+ * @returns `true` if `u` is `null` or `undefined`, `false` otherwise.
378
+ * When `true`, TypeScript narrows the type to `null | undefined`.
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * const value: string | null | undefined = getValue();
383
+ *
384
+ * if (isNullish(value)) {
385
+ * // value is now typed as null | undefined
386
+ * console.log('Value is nullish');
387
+ * } else {
388
+ * // value is now typed as string
389
+ * console.log('Value length:', value.length);
390
+ * }
391
+ * ```
392
+ */
393
+ export const isNullish = (u: unknown): u is null | undefined => u == null;
394
+
395
+ /**
396
+ * Type guard that checks if a value is not `null` or `undefined` (non-nullish).
397
+ *
398
+ * This function uses the loose inequality operator (`!=`) to check that a value is neither
399
+ * `null` nor `undefined` in a single comparison. This is equivalent to TypeScript's
400
+ * `NonNullable<T>` utility type.
401
+ *
402
+ * **Type Narrowing Behavior:**
403
+ * - Excludes both `null` and `undefined` from the input type when `true`
404
+ * - Equivalent to applying TypeScript's `NonNullable<T>` utility type
405
+ * - Commonly used to filter out nullish values from arrays
406
+ *
407
+ * @template T - The type of the input value
408
+ * @param u - The value to check
409
+ * @returns `true` if `u` is not `null` and not `undefined`, `false` otherwise.
410
+ * When `true`, TypeScript narrows the type to `NonNullable<T>`.
411
+ *
412
+ * @example
413
+ * ```typescript
414
+ * const items: (string | null | undefined)[] = [
415
+ * 'hello',
416
+ * null,
417
+ * 'world',
418
+ * undefined,
419
+ * 'test'
420
+ * ];
421
+ *
422
+ * const definedItems = items.filter(isNonNullish);
423
+ * // definedItems is now string[] - both null and undefined values are filtered out
424
+ *
425
+ * definedItems.forEach(item => {
426
+ * // item is guaranteed to be string, never null or undefined
427
+ * console.log(item.toUpperCase());
428
+ * });
429
+ * ```
430
+ *
431
+ * @example
432
+ * Progressive validation with optional chaining alternative:
433
+ * ```typescript
434
+ * interface User {
435
+ * profile?: {
436
+ * name?: string;
437
+ * email?: string;
438
+ * };
439
+ * }
440
+ *
441
+ * const user: User = getUser();
442
+ *
443
+ * // Instead of optional chaining: user.profile?.name
444
+ * if (isNonNullish(user.profile) && isNonNullish(user.profile.name)) {
445
+ * // user.profile.name is now guaranteed to be string
446
+ * console.log('User name:', user.profile.name.toUpperCase());
447
+ * }
448
+ * ```
449
+ */
450
+ export const isNonNullish = <T,>(u: T): u is NonNullable<T> => u != null;