@wopjs/cast 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ type _ = undefined;
2
2
  /** Returns `U` if `T` is `never` or `any`, otherwise returns `T`. */
3
3
  type SetDefaultType<T, U> = [T, U][T extends any ? (0 extends 1 & T ? 1 : 0) : 1];
4
4
  /** Returns `true` if `x` is not `undefined`. */
5
- declare const isDefined: <T>(x: T | undefined) => x is T;
5
+ declare const isDefined: <T>(x: T | _) => x is Exclude<T, _>;
6
6
  declare const isTrue: (x: unknown) => x is true;
7
7
  /** Returns `true` if `x` is `true`, otherwise returns `undefined`. */
8
8
  declare const toTrue: (x: unknown) => true | _;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ type _ = undefined;
2
2
  /** Returns `U` if `T` is `never` or `any`, otherwise returns `T`. */
3
3
  type SetDefaultType<T, U> = [T, U][T extends any ? (0 extends 1 & T ? 1 : 0) : 1];
4
4
  /** Returns `true` if `x` is not `undefined`. */
5
- declare const isDefined: <T>(x: T | undefined) => x is T;
5
+ declare const isDefined: <T>(x: T | _) => x is Exclude<T, _>;
6
6
  declare const isTrue: (x: unknown) => x is true;
7
7
  /** Returns `true` if `x` is `true`, otherwise returns `undefined`. */
8
8
  declare const toTrue: (x: unknown) => true | _;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/is-to-as.ts","../src/returns.ts"],"names":[],"mappings":";;;AAAA,IAAM,CAAA,GAAI,MAAA;AAOH,IAAM,SAAA,GAAY,CAAI,CAAA,KAA6B,CAAA,KAAM;AAEzD,IAAM,MAAA,GAAS,CAAC,CAAA,KAA0B,CAAA,KAAM;AAGhD,IAAM,MAAA,GAAS,CAAC,CAAA,KAA0B,CAAA,KAAM,OAAO,IAAA,GAAO;AAG9D,IAAM,MAAA,GAAS,CAAC,CAAA,KAAyB,CAAA,KAAM,OAAO,CAAA,GAAI;AAO1D,IAAM,OAAA,GAAU,CAAI,CAAA,KAA+B,CAAC;AAGpD,IAAM,UAAU,CAAI,CAAA,KAA+B,OAAA,CAAQ,CAAC,IAAI,CAAA,GAAI;AAGpE,IAAM,QAAA,GAAW,CAAI,CAAA,KAAiC,CAAC,CAAC;AAGxD,IAAM,WAAW,CAAI,CAAA,KAAiC,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI;AAExE,IAAM,SAAA,GAAY,CAAC,CAAA,KAA6B,CAAA,KAAM,QAAQ,CAAA,KAAM;AAGpE,IAAM,YAAY,CAAC,CAAA,KAA6B,SAAA,CAAU,CAAC,IAAI,CAAA,GAAI;AAGnE,IAAM,WAAW,CAAC,CAAA,KAA4B,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM;AAG7E,IAAM,WAAW,CAAC,CAAA,KAA4B,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI;AAGhE,IAAM,WAAW,CAAC,CAAA,KAAwB,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI;AAG5D,IAAM,QAAA,GAAW,CAAC,CAAA,KAA4B,OAAO,CAAA,KAAM;AAG3D,IAAM,WAAW,CAAC,CAAA,KAA4B,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI;AAGhE,IAAM,WAAW,CAAC,CAAA,KAAwB,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI;AAG5D,IAAM,mBAAmB,CAAC,CAAA,KAA4B,QAAA,CAAS,CAAC,KAAK,CAAA,KAAM;AAG3E,IAAM,mBAAmB,CAAC,CAAA,KAA4B,gBAAA,CAAiB,CAAC,IAAI,CAAA,GAAI;AAKhF,IAAM,UAAU,KAAA,CAAM;AAGtB,IAAM,UAAU,CAAI,CAAA,KAA+B,OAAA,CAAQ,CAAC,IAAI,CAAA,GAAI;AAGpE,IAAM,UAAU,CAAI,CAAA,KAA2B,QAAQ,CAAC,CAAA,GAAI,IAAK;AAGjE,IAAM,kBAAkB,CAAI,CAAA,KAA+B,QAAQ,CAAC,CAAA,IAAK,EAAE,MAAA,GAAS;AAGpF,IAAM,kBAAkB,CAAI,CAAA,KAA+B,eAAA,CAAgB,CAAC,IAAI,CAAA,GAAI;AAKpF,IAAM,WAAW,CAAI,CAAA,KAAgC,CAAA,KAAM,IAAA,IAAQ,OAAO,CAAA,KAAM;AAGhF,IAAM,WAAW,CAAI,CAAA,KAAgC,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI;AAGvE,IAAM,WAAW,CAAI,CAAA,KAA4B,SAAS,CAAC,CAAA,GAAI,IAAK;AASpE,IAAM,aAAA,GAAgB,CAAI,CAAA,KAAqC,QAAA,CAAS,CAAC,CAAA,IAAK,CAAC,QAAQ,CAAC;AAGxF,IAAM,gBAAgB,CAAI,CAAA,KAAqC,aAAA,CAAc,CAAC,IAAI,CAAA,GAAI;AAGtF,IAAM,gBAAgB,CAAI,CAAA,KAAiC,cAAc,CAAC,CAAA,GAAI,IAAK;AAE1F,IAAM,qBAAA,GAAwB,CAAI,CAAA,EAAM,SAAA,KAAiD;AACvF,EAAA,IAAI,aAAA,CAAc,CAAC,CAAA,EAAG;AACpB,IAAA,KAAA,IAAS,OAAO,CAAA,EAAG;AACjB,MAAA,IAAI,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,GAAG,CAAA,KAAM,CAAC,SAAA,IAAa,SAAA,CAAU,CAAA,CAAE,GAAG,CAAC,CAAA,CAAA,EAAI;AAC9D,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT,CAAA;AAGO,IAAM,qBAAA,GAAwB,CAAI,CAAA,KAAqC,qBAAA,CAAsB,CAAC;AAG9F,IAAM,wBAAwB,CAAI,CAAA,KAAqC,qBAAA,CAAsB,CAAC,IAAI,CAAA,GAAI;AAGtG,IAAM,oBAAA,GAAuB,CAAI,CAAA,KAAqC,qBAAA,CAAsB,GAAG,SAAS;AAGxG,IAAM,uBAAuB,CAAI,CAAA,KAAqC,oBAAA,CAAqB,CAAC,IAAI,CAAA,GAAI;AAQpG,IAAM,eAAA,GAAkB,CAC7B,CAAA,EACA,CAAA,KAC+B;AAC/B,EAAA,IAAI,aAAA,CAAc,CAAC,CAAA,EAAG;AACpB,IAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,IAAA,IAAI,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AACzB,IAAA,IAAI,SAAS,KAAA,CAAM,MAAA;AACnB,IAAA,IAAI,MAAA;AAEJ,IAAA,OAAO,EAAE,QAAQ,MAAA,EAAQ;AACvB,MAAA,IAAI,GAAA,GAAM,MAAM,KAAK,CAAA;AACrB,MAAA,IAAI,KAAA,GAAQ,EAAE,GAAG,CAAA;AACjB,MAAA,IAAI,CAAA,CAAE,KAAK,CAAA,EAAG;AACZ,QAAA,CAAC,MAAA,KAAW,EAAC,EAAG,GAAG,CAAA,GAAI,KAAA;AAAA,MACzB;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAGO,IAAM,mBAAA,GAAsB,CAAC,CAAA,KAA8C,eAAA,CAAgB,GAAG,MAAM;AAOpG,IAAM,KAAA,GAAQ,CAAC,CAAA,KAAuB;AAC3C,EAAA,IAAI,QAAA,CAAS,CAAC,CAAA,EAAG,OAAO,CAAA;AACxB,EAAA,IAAI,CAAA,IAAK,MAAM,OAAO,EAAA;AACtB,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,IAAA,EAAM,CAAC,CAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,CAAA,GAAI,EAAA;AAAA,EACb;AACF;;;AC7KO,IAAM,OAAO,MAAY;AAAC;AAE1B,IAAM,gBAAA,GAAmB;AAEzB,IAAM,cAAc,MAAY;AAEhC,IAAM,eAAe,MAAa;AAElC,IAAM,cAAc,MAAY;AAEhC,IAAM,qBAAqB,MAAc","file":"index.js"}
1
+ {"version":3,"sources":["../src/is-to-as.ts","../src/returns.ts"],"names":[],"mappings":"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","file":"index.js"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/is-to-as.ts","../src/returns.ts"],"names":[],"mappings":"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","file":"index.mjs"}
1
+ {"version":3,"sources":["../src/is-to-as.ts","../src/returns.ts"],"names":[],"mappings":"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","file":"index.mjs"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wopjs/cast",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Type-safe utilities for filtering and coercing unknown values in TypeScript.",
5
5
  "repository": "wopjs/cast",
6
6
  "main": "./dist/index.js",
@@ -41,12 +41,40 @@ import {
41
41
  toTruthy,
42
42
  } from ".";
43
43
 
44
+ /** Bypass TypeScript static type inference. */
44
45
  const castType = <T>(x: T): T => x;
45
46
 
46
47
  describe("primitive.ts", () => {
47
48
  it("isDefined", () => {
48
49
  expect(isDefined(1)).toBe(true);
49
50
  expect(isDefined(undefined)).toBe(false);
51
+
52
+ {
53
+ // Type narrowing - excludes undefined from type
54
+ const val = castType<string>("hello");
55
+ if (isDefined(val)) {
56
+ const check: string = val;
57
+ expect(check).toBe("hello");
58
+ }
59
+ }
60
+
61
+ {
62
+ // Type narrowing - excludes undefined from union
63
+ const val = castType<string | undefined>("hello");
64
+ if (isDefined(val)) {
65
+ const check: string = val;
66
+ expect(check).toBe("hello");
67
+ }
68
+ }
69
+
70
+ {
71
+ // Type narrowing - excludes undefined but keeps null
72
+ const val = castType<number | null | undefined>(42);
73
+ if (isDefined(val)) {
74
+ const check: number | null = val;
75
+ expect(check).toBe(42);
76
+ }
77
+ }
50
78
  });
51
79
 
52
80
  it("isTrue", () => {
@@ -236,15 +264,242 @@ describe("primitive.ts", () => {
236
264
  });
237
265
 
238
266
  it("isNonEmptyString", () => {
267
+ // Runtime behavior - truthy cases
239
268
  expect(isNonEmptyString("hello")).toBe(true);
269
+ expect(isNonEmptyString("a")).toBe(true);
270
+ expect(isNonEmptyString(" ")).toBe(true);
271
+ expect(isNonEmptyString(" ")).toBe(true);
272
+ expect(isNonEmptyString("\t")).toBe(true);
273
+ expect(isNonEmptyString("\n")).toBe(true);
274
+ expect(isNonEmptyString("\r\n")).toBe(true);
275
+ expect(isNonEmptyString("0")).toBe(true);
276
+ expect(isNonEmptyString("false")).toBe(true);
277
+ expect(isNonEmptyString("null")).toBe(true);
278
+ expect(isNonEmptyString("undefined")).toBe(true);
279
+ expect(isNonEmptyString("Hello, 世界")).toBe(true);
280
+ expect(isNonEmptyString("🎉")).toBe(true);
281
+ expect(isNonEmptyString("\u0000")).toBe(true); // null character
282
+ expect(isNonEmptyString(String("hello"))).toBe(true);
283
+
284
+ // Runtime behavior - falsy cases
240
285
  expect(isNonEmptyString("")).toBe(false);
286
+ expect(isNonEmptyString(String(""))).toBe(false);
241
287
  expect(isNonEmptyString(1)).toBe(false);
288
+ expect(isNonEmptyString(0)).toBe(false);
289
+ expect(isNonEmptyString(-1)).toBe(false);
290
+ expect(isNonEmptyString(NaN)).toBe(false);
291
+ expect(isNonEmptyString(Infinity)).toBe(false);
292
+ expect(isNonEmptyString(true)).toBe(false);
293
+ expect(isNonEmptyString(false)).toBe(false);
294
+ expect(isNonEmptyString(null)).toBe(false);
295
+ expect(isNonEmptyString(undefined)).toBe(false);
296
+ expect(isNonEmptyString({})).toBe(false);
297
+ expect(isNonEmptyString({ toString: () => "hello" })).toBe(false);
298
+ expect(isNonEmptyString([])).toBe(false);
299
+ expect(isNonEmptyString(["a", "b"])).toBe(false);
300
+ expect(isNonEmptyString(() => "hello")).toBe(false);
301
+ expect(isNonEmptyString(Symbol("hello"))).toBe(false);
302
+ expect(isNonEmptyString(new Date())).toBe(false);
303
+ expect(isNonEmptyString(/regex/)).toBe(false);
304
+ expect(isNonEmptyString(new String("hello"))).toBe(false); // String object, not primitive
305
+
306
+ {
307
+ // Type narrowing - unknown input narrows to string
308
+ const str = castType<unknown>("hello");
309
+ if (isNonEmptyString(str)) {
310
+ const check: string = str;
311
+ expect(check).toBe("hello");
312
+ } else {
313
+ throw new Error("Unreachable");
314
+ }
315
+ }
316
+
317
+ {
318
+ // Type narrowing - empty string returns false
319
+ const str = castType<string>("");
320
+ if (isNonEmptyString(str)) {
321
+ const _check: string = str;
322
+ throw new Error("Unreachable");
323
+ } else {
324
+ expect(str).toBe("");
325
+ }
326
+ }
327
+
328
+ {
329
+ // Type narrowing - extracts string from union
330
+ const str = castType<string | number>("hello");
331
+ if (isNonEmptyString(str)) {
332
+ const check: string = str;
333
+ expect(check).toBe("hello");
334
+ } else {
335
+ const _check: string | number = str;
336
+ throw new Error("Unreachable");
337
+ }
338
+ }
339
+
340
+ {
341
+ // Type narrowing - number in union returns false
342
+ const str = castType<string | number>(42);
343
+ if (isNonEmptyString(str)) {
344
+ const _check: string = str;
345
+ throw new Error("Unreachable");
346
+ } else {
347
+ const check: string | number = str;
348
+ expect(check).toBe(42);
349
+ }
350
+ }
351
+
352
+ {
353
+ // Type narrowing - null | string union
354
+ const str = castType<string | null>("hello");
355
+ if (isNonEmptyString(str)) {
356
+ const check: string = str;
357
+ expect(check).toBe("hello");
358
+ } else {
359
+ throw new Error("Unreachable");
360
+ }
361
+ }
362
+
363
+ {
364
+ // Type narrowing - null returns false
365
+ const str = castType<string | null>(null);
366
+ if (isNonEmptyString(str)) {
367
+ const _check: string = str;
368
+ throw new Error("Unreachable");
369
+ } else {
370
+ const check: string | null = str;
371
+ expect(check).toBe(null);
372
+ }
373
+ }
374
+
375
+ {
376
+ // Type narrowing - any input
377
+ const str = castType<any>("hello");
378
+ if (isNonEmptyString(str)) {
379
+ const check: string = str;
380
+ expect(check).toBe("hello");
381
+ }
382
+ }
383
+
384
+ {
385
+ // Type narrowing - generic function
386
+ const _fn = <T>(x: T): void => {
387
+ if (isNonEmptyString(x)) {
388
+ const y: string = x;
389
+ expect(typeof y).toBe("string");
390
+ }
391
+ };
392
+ }
242
393
  });
243
394
 
244
395
  it("toNonEmptyString", () => {
396
+ // Runtime behavior - returns value for non-empty strings
245
397
  expect(toNonEmptyString("hello")).toBe("hello");
398
+ expect(toNonEmptyString("a")).toBe("a");
399
+ expect(toNonEmptyString(" ")).toBe(" ");
400
+ expect(toNonEmptyString(" ")).toBe(" ");
401
+ expect(toNonEmptyString("\t")).toBe("\t");
402
+ expect(toNonEmptyString("\n")).toBe("\n");
403
+ expect(toNonEmptyString("\r\n")).toBe("\r\n");
404
+ expect(toNonEmptyString("0")).toBe("0");
405
+ expect(toNonEmptyString("false")).toBe("false");
406
+ expect(toNonEmptyString("null")).toBe("null");
407
+ expect(toNonEmptyString("undefined")).toBe("undefined");
408
+ expect(toNonEmptyString("Hello, 世界")).toBe("Hello, 世界");
409
+ expect(toNonEmptyString("🎉")).toBe("🎉");
410
+ expect(toNonEmptyString("\u0000")).toBe("\u0000");
411
+ expect(toNonEmptyString(String("hello"))).toBe("hello");
412
+
413
+ // Runtime behavior - returns undefined for empty string and non-strings
246
414
  expect(toNonEmptyString("")).toBe(undefined);
415
+ expect(toNonEmptyString(String(""))).toBe(undefined);
247
416
  expect(toNonEmptyString(1)).toBe(undefined);
417
+ expect(toNonEmptyString(0)).toBe(undefined);
418
+ expect(toNonEmptyString(-1)).toBe(undefined);
419
+ expect(toNonEmptyString(NaN)).toBe(undefined);
420
+ expect(toNonEmptyString(Infinity)).toBe(undefined);
421
+ expect(toNonEmptyString(true)).toBe(undefined);
422
+ expect(toNonEmptyString(false)).toBe(undefined);
423
+ expect(toNonEmptyString(null)).toBe(undefined);
424
+ expect(toNonEmptyString(undefined)).toBe(undefined);
425
+ expect(toNonEmptyString({})).toBe(undefined);
426
+ expect(toNonEmptyString({ toString: () => "hello" })).toBe(undefined);
427
+ expect(toNonEmptyString([])).toBe(undefined);
428
+ expect(toNonEmptyString(["a", "b"])).toBe(undefined);
429
+ expect(toNonEmptyString(() => "hello")).toBe(undefined);
430
+ expect(toNonEmptyString(Symbol("hello"))).toBe(undefined);
431
+ expect(toNonEmptyString(new Date())).toBe(undefined);
432
+ expect(toNonEmptyString(/regex/)).toBe(undefined);
433
+ expect(toNonEmptyString(new String("hello"))).toBe(undefined);
434
+
435
+ {
436
+ // Type narrowing - unknown input returns string | undefined
437
+ const str = castType<unknown>("hello");
438
+ const result: string | undefined = toNonEmptyString(str);
439
+ expect(result).toBe("hello");
440
+ }
441
+
442
+ {
443
+ // Type narrowing - empty string returns undefined
444
+ const str = castType<string>("");
445
+ const result = toNonEmptyString(str);
446
+ expect(result).toBe(undefined);
447
+ }
448
+
449
+ {
450
+ // Type narrowing - extracts string from union
451
+ const str = castType<string | number>("hello");
452
+ const result = toNonEmptyString(str);
453
+ if (result) {
454
+ const check: string = result;
455
+ expect(check).toBe("hello");
456
+ }
457
+ }
458
+
459
+ {
460
+ // Type narrowing - number in union returns undefined
461
+ const str = castType<string | number>(42);
462
+ const result = toNonEmptyString(str);
463
+ expect(result).toBe(undefined);
464
+ }
465
+
466
+ {
467
+ // Type narrowing - null | string union
468
+ const str = castType<string | null>("hello");
469
+ const result = toNonEmptyString(str);
470
+ if (result) {
471
+ const check: string = result;
472
+ expect(check).toBe("hello");
473
+ }
474
+ }
475
+
476
+ {
477
+ // Type narrowing - null returns undefined
478
+ const str = castType<string | null>(null);
479
+ const result = toNonEmptyString(str);
480
+ expect(result).toBe(undefined);
481
+ }
482
+
483
+ {
484
+ // Type narrowing - any input returns string | undefined
485
+ const str = castType<any>("hello");
486
+ const result: string | undefined = toNonEmptyString(str);
487
+ expect(result).toBe("hello");
488
+ }
489
+
490
+ {
491
+ // Type narrowing - optional chaining works
492
+ const str = castType<unknown>("hello");
493
+ const upper = toNonEmptyString(str)?.toUpperCase();
494
+ expect(upper).toBe("HELLO");
495
+ }
496
+
497
+ {
498
+ // Type narrowing - optional chaining with empty string
499
+ const str = castType<unknown>("");
500
+ const upper = toNonEmptyString(str)?.toUpperCase();
501
+ expect(upper).toBe(undefined);
502
+ }
248
503
  });
249
504
 
250
505
  it("isArray", () => {
@@ -395,14 +650,54 @@ describe("primitive.ts", () => {
395
650
  });
396
651
 
397
652
  it("isNonEmptyArray", () => {
398
- // Runtime behavior
653
+ // Runtime behavior - truthy cases
399
654
  expect(isNonEmptyArray([1])).toBe(true);
400
655
  expect(isNonEmptyArray([1, 2, 3])).toBe(true);
656
+ expect(isNonEmptyArray(["a", "b", "c"])).toBe(true);
657
+ expect(isNonEmptyArray([undefined])).toBe(true);
658
+ expect(isNonEmptyArray([null])).toBe(true);
659
+ expect(isNonEmptyArray([false])).toBe(true);
660
+ expect(isNonEmptyArray([0])).toBe(true);
661
+ expect(isNonEmptyArray([""])).toBe(true);
662
+ expect(isNonEmptyArray([{}])).toBe(true);
663
+ expect(isNonEmptyArray([[]])).toBe(true);
664
+ expect(isNonEmptyArray([() => {}])).toBe(true);
665
+ expect(isNonEmptyArray(new Array(1).fill(undefined))).toBe(true);
666
+ expect(isNonEmptyArray(Array.from({ length: 1 }))).toBe(true);
667
+ // eslint-disable-next-line no-sparse-arrays
668
+ expect(isNonEmptyArray([, , 1])).toBe(true); // sparse array with value
669
+ expect(isNonEmptyArray(Object.assign([], { 0: "a" }))).toBe(true);
670
+
671
+ // Runtime behavior - falsy cases
401
672
  expect(isNonEmptyArray([])).toBe(false);
673
+ expect(isNonEmptyArray([])).toBe(false);
674
+ expect(isNonEmptyArray(new Array(0))).toBe(false);
675
+ expect(isNonEmptyArray(Array.from({ length: 0 }))).toBe(false);
402
676
  expect(isNonEmptyArray({})).toBe(false);
677
+ expect(isNonEmptyArray({ length: 1, 0: "a" })).toBe(false); // array-like object
678
+ expect(isNonEmptyArray({ length: 0 })).toBe(false);
403
679
  expect(isNonEmptyArray(null)).toBe(false);
404
680
  expect(isNonEmptyArray(undefined)).toBe(false);
405
681
  expect(isNonEmptyArray("string")).toBe(false);
682
+ expect(isNonEmptyArray("")).toBe(false);
683
+ expect(isNonEmptyArray("abc")).toBe(false); // string is not array
684
+ expect(isNonEmptyArray(123)).toBe(false);
685
+ expect(isNonEmptyArray(0)).toBe(false);
686
+ expect(isNonEmptyArray(NaN)).toBe(false);
687
+ expect(isNonEmptyArray(true)).toBe(false);
688
+ expect(isNonEmptyArray(false)).toBe(false);
689
+ expect(isNonEmptyArray(Symbol())).toBe(false);
690
+ expect(isNonEmptyArray(() => {})).toBe(false);
691
+ expect(isNonEmptyArray(function () {})).toBe(false);
692
+ expect(isNonEmptyArray(new Date())).toBe(false);
693
+ expect(isNonEmptyArray(/regex/)).toBe(false);
694
+ expect(isNonEmptyArray(new Map([[0, "a"]]))).toBe(false);
695
+ expect(isNonEmptyArray(new Set([1, 2]))).toBe(false);
696
+ expect(isNonEmptyArray(new Int8Array([1, 2]))).toBe(false); // typed arrays are not Array.isArray
697
+
698
+ // Sparse arrays (length > 0 but no actual elements)
699
+ const sparseArray = new Array(3);
700
+ expect(isNonEmptyArray(sparseArray)).toBe(true); // length is 3, so truthy
406
701
 
407
702
  {
408
703
  // Type narrowing - preserves array type
@@ -429,7 +724,7 @@ describe("primitive.ts", () => {
429
724
  }
430
725
 
431
726
  {
432
- // Type narrowing - extracts array from union
727
+ // Type narrowing - extracts array from union (string case)
433
728
  const arr = castType<string | string[]>("a");
434
729
  if (isNonEmptyArray(arr)) {
435
730
  const _check: string[] = arr;
@@ -440,6 +735,18 @@ describe("primitive.ts", () => {
440
735
  }
441
736
  }
442
737
 
738
+ {
739
+ // Type narrowing - empty array returns false
740
+ const arr = castType<string[]>([]);
741
+ if (isNonEmptyArray(arr)) {
742
+ const _check: string[] = arr;
743
+ throw new Error("Unreachable");
744
+ } else {
745
+ const check: string[] = arr;
746
+ expect(check).toEqual([]);
747
+ }
748
+ }
749
+
443
750
  {
444
751
  // Type narrowing - preserves readonly array
445
752
  const arr = castType<readonly number[]>([1, 2]);
@@ -487,6 +794,48 @@ describe("primitive.ts", () => {
487
794
  expect(check).toBe("hello");
488
795
  }
489
796
  }
797
+
798
+ {
799
+ // Type narrowing - null | array union
800
+ const arr = castType<number[] | null>([1, 2]);
801
+ if (isNonEmptyArray(arr)) {
802
+ const check: number[] = arr;
803
+ expect(check).toEqual([1, 2]);
804
+ } else {
805
+ throw new Error("Unreachable");
806
+ }
807
+ }
808
+
809
+ {
810
+ // Type narrowing - null returns false
811
+ const arr = castType<number[] | null>(null);
812
+ if (isNonEmptyArray(arr)) {
813
+ const _check: number[] = arr;
814
+ throw new Error("Unreachable");
815
+ } else {
816
+ const check: null = arr;
817
+ expect(check).toBe(null);
818
+ }
819
+ }
820
+
821
+ {
822
+ // Type narrowing - any input
823
+ const arr = castType<any>([1, 2]);
824
+ if (isNonEmptyArray(arr)) {
825
+ const check: unknown[] = arr;
826
+ expect(check).toEqual([1, 2]);
827
+ }
828
+ }
829
+
830
+ {
831
+ // Type narrowing - generic function
832
+ const _fn = <T>(x: T): void => {
833
+ if (isNonEmptyArray(x)) {
834
+ const y: readonly unknown[] = x;
835
+ expect(Array.isArray(y)).toBe(true);
836
+ }
837
+ };
838
+ }
490
839
  });
491
840
 
492
841
  it("asArray", () => {
@@ -539,8 +888,54 @@ describe("primitive.ts", () => {
539
888
  });
540
889
 
541
890
  it("toNonEmptyArray", () => {
891
+ // Runtime behavior - returns value for non-empty arrays
542
892
  expect(toNonEmptyArray([1])).toEqual([1]);
893
+ expect(toNonEmptyArray([1, 2, 3])).toEqual([1, 2, 3]);
894
+ expect(toNonEmptyArray(["a", "b", "c"])).toEqual(["a", "b", "c"]);
895
+ expect(toNonEmptyArray([undefined])).toEqual([undefined]);
896
+ expect(toNonEmptyArray([null])).toEqual([null]);
897
+ expect(toNonEmptyArray([false])).toEqual([false]);
898
+ expect(toNonEmptyArray([0])).toEqual([0]);
899
+ expect(toNonEmptyArray([""])).toEqual([""]);
900
+ expect(toNonEmptyArray([{}])).toEqual([{}]);
901
+ expect(toNonEmptyArray([[]])).toEqual([[]]);
902
+ const fn = () => {};
903
+ expect(toNonEmptyArray([fn])).toEqual([fn]);
904
+
905
+ // Returns same reference for non-empty arrays
906
+ const arr = [1, 2, 3];
907
+ expect(toNonEmptyArray(arr)).toBe(arr);
908
+
909
+ // Sparse arrays (length > 0)
910
+ const sparseArray = new Array(3);
911
+ expect(toNonEmptyArray(sparseArray)).toBe(sparseArray);
912
+
913
+ // Runtime behavior - returns undefined for empty arrays and non-arrays
914
+ expect(toNonEmptyArray([])).toBe(undefined);
543
915
  expect(toNonEmptyArray([])).toBe(undefined);
916
+ expect(toNonEmptyArray(new Array(0))).toBe(undefined);
917
+ expect(toNonEmptyArray(Array.from({ length: 0 }))).toBe(undefined);
918
+ expect(toNonEmptyArray({})).toBe(undefined);
919
+ expect(toNonEmptyArray({ length: 1, 0: "a" })).toBe(undefined); // array-like object
920
+ expect(toNonEmptyArray({ length: 0 })).toBe(undefined);
921
+ expect(toNonEmptyArray(null)).toBe(undefined);
922
+ expect(toNonEmptyArray(undefined)).toBe(undefined);
923
+ expect(toNonEmptyArray("string")).toBe(undefined);
924
+ expect(toNonEmptyArray("")).toBe(undefined);
925
+ expect(toNonEmptyArray("abc")).toBe(undefined);
926
+ expect(toNonEmptyArray(123)).toBe(undefined);
927
+ expect(toNonEmptyArray(0)).toBe(undefined);
928
+ expect(toNonEmptyArray(NaN)).toBe(undefined);
929
+ expect(toNonEmptyArray(true)).toBe(undefined);
930
+ expect(toNonEmptyArray(false)).toBe(undefined);
931
+ expect(toNonEmptyArray(Symbol())).toBe(undefined);
932
+ expect(toNonEmptyArray(() => {})).toBe(undefined);
933
+ expect(toNonEmptyArray(function () {})).toBe(undefined);
934
+ expect(toNonEmptyArray(new Date())).toBe(undefined);
935
+ expect(toNonEmptyArray(/regex/)).toBe(undefined);
936
+ expect(toNonEmptyArray(new Map([[0, "a"]]))).toBe(undefined);
937
+ expect(toNonEmptyArray(new Set([1, 2]))).toBe(undefined);
938
+ expect(toNonEmptyArray(new Int8Array([1, 2]))).toBe(undefined);
544
939
 
545
940
  {
546
941
  // Type narrowing - preserves array type
@@ -549,6 +944,8 @@ describe("primitive.ts", () => {
549
944
  if (result) {
550
945
  const check: string[] = result;
551
946
  expect(check).toBe(arr);
947
+ } else {
948
+ throw new Error("Unreachable");
552
949
  }
553
950
  }
554
951
 
@@ -562,6 +959,20 @@ describe("primitive.ts", () => {
562
959
  }
563
960
  }
564
961
 
962
+ {
963
+ // Type narrowing - string in union returns undefined
964
+ const arr = castType<string | string[]>("hello");
965
+ const result = toNonEmptyArray(arr);
966
+ expect(result).toBe(undefined);
967
+ }
968
+
969
+ {
970
+ // Type narrowing - empty array returns undefined
971
+ const arr = castType<string[]>([]);
972
+ const result = toNonEmptyArray(arr);
973
+ expect(result).toBe(undefined);
974
+ }
975
+
565
976
  {
566
977
  // Type narrowing - preserves readonly array
567
978
  const arr = castType<readonly number[]>([1, 2]);
@@ -583,7 +994,7 @@ describe("primitive.ts", () => {
583
994
  }
584
995
 
585
996
  {
586
- // Type narrowing - unknown input returns unknown[]
997
+ // Type narrowing - unknown input returns unknown[] | undefined
587
998
  const arr = castType<unknown>(["a", "b"]);
588
999
  let result = toNonEmptyArray(arr);
589
1000
  if (result) {
@@ -606,6 +1017,61 @@ describe("primitive.ts", () => {
606
1017
  throw new Error("Unreachable");
607
1018
  }
608
1019
  }
1020
+
1021
+ {
1022
+ // Type narrowing - null | array union
1023
+ const arr = castType<number[] | null>([1, 2]);
1024
+ const result = toNonEmptyArray(arr);
1025
+ if (result) {
1026
+ const check: number[] = result;
1027
+ expect(check).toEqual([1, 2]);
1028
+ }
1029
+ }
1030
+
1031
+ {
1032
+ // Type narrowing - null returns undefined
1033
+ const arr = castType<number[] | null>(null);
1034
+ const result = toNonEmptyArray(arr);
1035
+ expect(result).toBe(undefined);
1036
+ }
1037
+
1038
+ {
1039
+ // Type narrowing - undefined | array union
1040
+ const arr = castType<number[] | undefined>([1, 2]);
1041
+ const result = toNonEmptyArray(arr);
1042
+ if (result) {
1043
+ const check: number[] = result;
1044
+ expect(check).toEqual([1, 2]);
1045
+ }
1046
+ }
1047
+
1048
+ {
1049
+ // Type narrowing - any input returns unknown[] | undefined
1050
+ const arr = castType<any>([1, 2]);
1051
+ const result: unknown[] | undefined = toNonEmptyArray(arr);
1052
+ expect(result).toEqual([1, 2]);
1053
+ }
1054
+
1055
+ {
1056
+ // Type narrowing - optional chaining works
1057
+ const arr = castType<unknown>([1, 2, 3]);
1058
+ const length = toNonEmptyArray(arr)?.length;
1059
+ expect(length).toBe(3);
1060
+ }
1061
+
1062
+ {
1063
+ // Type narrowing - optional chaining with empty array
1064
+ const arr = castType<unknown>([]);
1065
+ const length = toNonEmptyArray(arr)?.length;
1066
+ expect(length).toBe(undefined);
1067
+ }
1068
+
1069
+ {
1070
+ // Type narrowing - map over result
1071
+ const arr = castType<number[]>([1, 2, 3]);
1072
+ const doubled = toNonEmptyArray(arr)?.map(x => x * 2);
1073
+ expect(doubled).toEqual([2, 4, 6]);
1074
+ }
609
1075
  });
610
1076
 
611
1077
  it("isObject", () => {
@@ -848,9 +1314,81 @@ describe("primitive.ts", () => {
848
1314
  });
849
1315
 
850
1316
  it("isNonEmptyPlainObject", () => {
1317
+ // Runtime behavior - truthy cases
851
1318
  expect(isNonEmptyPlainObject({ a: 1 })).toBe(true);
1319
+ expect(isNonEmptyPlainObject({ a: undefined })).toBe(true);
1320
+ expect(isNonEmptyPlainObject({ a: null })).toBe(true);
1321
+ expect(isNonEmptyPlainObject({ a: false })).toBe(true);
1322
+ expect(isNonEmptyPlainObject({ a: 0 })).toBe(true);
1323
+ expect(isNonEmptyPlainObject({ a: "" })).toBe(true);
1324
+ expect(isNonEmptyPlainObject({ "": 1 })).toBe(true);
1325
+ expect(isNonEmptyPlainObject({ 0: "a" })).toBe(true);
1326
+ expect(isNonEmptyPlainObject({ a: 1, b: 2, c: 3 })).toBe(true);
1327
+ expect(isNonEmptyPlainObject({ nested: { deep: { value: 1 } } })).toBe(true);
1328
+ expect(isNonEmptyPlainObject(Object.create(null, { a: { value: 1, enumerable: true } }))).toBe(true);
1329
+
1330
+ // Runtime behavior - falsy cases
852
1331
  expect(isNonEmptyPlainObject({})).toBe(false);
853
1332
  expect(isNonEmptyPlainObject([])).toBe(false);
1333
+ expect(isNonEmptyPlainObject([1, 2, 3])).toBe(false);
1334
+ expect(isNonEmptyPlainObject("hello")).toBe(false);
1335
+ expect(isNonEmptyPlainObject("")).toBe(false);
1336
+ expect(isNonEmptyPlainObject(1)).toBe(false);
1337
+ expect(isNonEmptyPlainObject(0)).toBe(false);
1338
+ expect(isNonEmptyPlainObject(NaN)).toBe(false);
1339
+ expect(isNonEmptyPlainObject(null)).toBe(false);
1340
+ expect(isNonEmptyPlainObject(undefined)).toBe(false);
1341
+ expect(isNonEmptyPlainObject(false)).toBe(false);
1342
+ expect(isNonEmptyPlainObject(true)).toBe(false);
1343
+ expect(isNonEmptyPlainObject(Symbol())).toBe(false);
1344
+ expect(isNonEmptyPlainObject(() => {})).toBe(false);
1345
+ expect(isNonEmptyPlainObject(function () {})).toBe(false);
1346
+ expect(isNonEmptyPlainObject(new Date())).toBe(false);
1347
+ expect(isNonEmptyPlainObject(/regex/)).toBe(false);
1348
+ expect(isNonEmptyPlainObject(new Map([["a", 1]]))).toBe(false);
1349
+ expect(isNonEmptyPlainObject(new Set([1, 2]))).toBe(false);
1350
+
1351
+ // Objects with only inherited properties (no own properties)
1352
+ const proto = { inherited: 1 };
1353
+ const objWithInherited = Object.create(proto);
1354
+ expect(isNonEmptyPlainObject(objWithInherited)).toBe(false);
1355
+
1356
+ // Objects with own properties shadow inherited
1357
+ const objWithOwn = Object.create(proto);
1358
+ objWithOwn.own = 2;
1359
+ expect(isNonEmptyPlainObject(objWithOwn)).toBe(true);
1360
+
1361
+ // Objects with symbol keys (symbols are not enumerated by for...in)
1362
+ const sym = Symbol("key");
1363
+ const objWithSymbol = { [sym]: 1 };
1364
+ expect(isNonEmptyPlainObject(objWithSymbol)).toBe(false);
1365
+
1366
+ // Objects with both string and symbol keys
1367
+ const objWithBoth = { a: 1, [sym]: 2 };
1368
+ expect(isNonEmptyPlainObject(objWithBoth)).toBe(true);
1369
+
1370
+ // Objects with non-enumerable properties
1371
+ const objWithNonEnumerable = {};
1372
+ Object.defineProperty(objWithNonEnumerable, "hidden", { value: 1, enumerable: false });
1373
+ expect(isNonEmptyPlainObject(objWithNonEnumerable)).toBe(false);
1374
+
1375
+ // Object.create(null) with properties
1376
+ const nullProtoObj = Object.create(null);
1377
+ nullProtoObj.a = 1;
1378
+ expect(isNonEmptyPlainObject(nullProtoObj)).toBe(true);
1379
+
1380
+ // Empty Object.create(null)
1381
+ expect(isNonEmptyPlainObject(Object.create(null))).toBe(false);
1382
+
1383
+ // Class instances (they are plain objects in the shallow sense)
1384
+ class MyClass {
1385
+ prop = 1;
1386
+ }
1387
+ expect(isNonEmptyPlainObject(new MyClass())).toBe(true);
1388
+
1389
+ // Empty class instance
1390
+ class EmptyClass {}
1391
+ expect(isNonEmptyPlainObject(new EmptyClass())).toBe(false);
854
1392
 
855
1393
  {
856
1394
  // Type narrowing - unknown input narrows to PlainObject
@@ -858,6 +1396,8 @@ describe("primitive.ts", () => {
858
1396
  if (isNonEmptyPlainObject(obj)) {
859
1397
  const check: PlainObject = obj;
860
1398
  expect(check).toEqual({ a: 1 });
1399
+ } else {
1400
+ throw new Error("Unreachable");
861
1401
  }
862
1402
  }
863
1403
 
@@ -865,8 +1405,8 @@ describe("primitive.ts", () => {
865
1405
  // Type narrowing - empty object returns false
866
1406
  const obj = castType<{ a?: number }>({});
867
1407
  if (isNonEmptyPlainObject(obj)) {
868
- const check: PlainObject = obj;
869
- expect(check).toEqual({});
1408
+ const _check: { a?: number } = obj;
1409
+ throw new Error("Unreachable");
870
1410
  } else {
871
1411
  expect(obj).toEqual({});
872
1412
  }
@@ -875,16 +1415,158 @@ describe("primitive.ts", () => {
875
1415
  {
876
1416
  // Type narrowing - excludes array
877
1417
  const obj = castType<{ a: number } | number[]>({ a: 1 });
1418
+ if (isNonEmptyPlainObject(obj)) {
1419
+ const check: { a: number } = obj;
1420
+ expect(check).toEqual({ a: 1 });
1421
+ } else {
1422
+ const _check: number[] = obj;
1423
+ throw new Error("Unreachable");
1424
+ }
1425
+ }
1426
+
1427
+ {
1428
+ // Type narrowing - array returns false
1429
+ const arr = castType<{ a: number } | number[]>([1, 2, 3]);
1430
+ if (isNonEmptyPlainObject(arr)) {
1431
+ const _check: { a: number } = arr;
1432
+ throw new Error("Unreachable");
1433
+ } else {
1434
+ const check: number[] = arr;
1435
+ expect(check).toEqual([1, 2, 3]);
1436
+ }
1437
+ }
1438
+
1439
+ {
1440
+ // Type narrowing - null | object union extracts PlainObject
1441
+ const obj = castType<null | { x: number }>({ x: 42 });
1442
+ if (isNonEmptyPlainObject(obj)) {
1443
+ const check: { x: number } = obj;
1444
+ expect(check).toEqual({ x: 42 });
1445
+ } else {
1446
+ const _check: null = obj;
1447
+ throw new Error("Unreachable");
1448
+ }
1449
+ }
1450
+
1451
+ {
1452
+ // Type narrowing - null returns false
1453
+ const obj = castType<null | { x: number }>(null);
1454
+ if (isNonEmptyPlainObject(obj)) {
1455
+ const _check: { x: number } = obj;
1456
+ throw new Error("Unreachable");
1457
+ } else {
1458
+ const check: null = obj;
1459
+ expect(check).toBe(null);
1460
+ }
1461
+ }
1462
+
1463
+ {
1464
+ // Type narrowing - preserves object type
1465
+ const obj = castType<{ a: string; b: number }>({ a: "hello", b: 42 });
1466
+ if (isNonEmptyPlainObject(obj)) {
1467
+ const check: { a: string; b: number } = obj;
1468
+ expect(check).toEqual({ a: "hello", b: 42 });
1469
+ } else {
1470
+ throw new Error("Unreachable");
1471
+ }
1472
+ }
1473
+
1474
+ {
1475
+ // Type narrowing - any input
1476
+ const obj = castType<any>({ a: 1 });
878
1477
  if (isNonEmptyPlainObject(obj)) {
879
1478
  const check: PlainObject = obj;
880
1479
  expect(check).toEqual({ a: 1 });
881
1480
  }
882
1481
  }
1482
+
1483
+ {
1484
+ // Type narrowing - generic function
1485
+ const _fn = <T>(x: T): void => {
1486
+ if (isNonEmptyPlainObject(x)) {
1487
+ const y: object = x;
1488
+ expect(typeof y).toBe("object");
1489
+ }
1490
+ };
1491
+ }
883
1492
  });
884
1493
 
885
1494
  it("toNonEmptyPlainObject", () => {
1495
+ // Runtime behavior - returns value for non-empty plain objects
886
1496
  expect(toNonEmptyPlainObject({ a: 1 })).toEqual({ a: 1 });
1497
+ expect(toNonEmptyPlainObject({ a: undefined })).toEqual({ a: undefined });
1498
+ expect(toNonEmptyPlainObject({ a: null })).toEqual({ a: null });
1499
+ expect(toNonEmptyPlainObject({ a: false })).toEqual({ a: false });
1500
+ expect(toNonEmptyPlainObject({ a: 0 })).toEqual({ a: 0 });
1501
+ expect(toNonEmptyPlainObject({ a: "" })).toEqual({ a: "" });
1502
+ expect(toNonEmptyPlainObject({ "": 1 })).toEqual({ "": 1 });
1503
+ expect(toNonEmptyPlainObject({ 0: "a" })).toEqual({ 0: "a" });
1504
+ expect(toNonEmptyPlainObject({ a: 1, b: 2, c: 3 })).toEqual({ a: 1, b: 2, c: 3 });
1505
+ expect(toNonEmptyPlainObject({ nested: { deep: { value: 1 } } })).toEqual({ nested: { deep: { value: 1 } } });
1506
+
1507
+ // Runtime behavior - returns undefined for empty or non-objects
887
1508
  expect(toNonEmptyPlainObject({})).toBe(undefined);
1509
+ expect(toNonEmptyPlainObject([])).toBe(undefined);
1510
+ expect(toNonEmptyPlainObject([1, 2, 3])).toBe(undefined);
1511
+ expect(toNonEmptyPlainObject("hello")).toBe(undefined);
1512
+ expect(toNonEmptyPlainObject("")).toBe(undefined);
1513
+ expect(toNonEmptyPlainObject(1)).toBe(undefined);
1514
+ expect(toNonEmptyPlainObject(0)).toBe(undefined);
1515
+ expect(toNonEmptyPlainObject(NaN)).toBe(undefined);
1516
+ expect(toNonEmptyPlainObject(null)).toBe(undefined);
1517
+ expect(toNonEmptyPlainObject(undefined)).toBe(undefined);
1518
+ expect(toNonEmptyPlainObject(false)).toBe(undefined);
1519
+ expect(toNonEmptyPlainObject(true)).toBe(undefined);
1520
+ expect(toNonEmptyPlainObject(Symbol())).toBe(undefined);
1521
+ expect(toNonEmptyPlainObject(() => {})).toBe(undefined);
1522
+ expect(toNonEmptyPlainObject(function () {})).toBe(undefined);
1523
+ expect(toNonEmptyPlainObject(new Date())).toBe(undefined);
1524
+ expect(toNonEmptyPlainObject(/regex/)).toBe(undefined);
1525
+ expect(toNonEmptyPlainObject(new Map([["a", 1]]))).toBe(undefined);
1526
+ expect(toNonEmptyPlainObject(new Set([1, 2]))).toBe(undefined);
1527
+
1528
+ // Objects with only inherited properties (no own properties)
1529
+ const proto = { inherited: 1 };
1530
+ const objWithInherited = Object.create(proto);
1531
+ expect(toNonEmptyPlainObject(objWithInherited)).toBe(undefined);
1532
+
1533
+ // Objects with own properties shadow inherited
1534
+ const objWithOwn = Object.create(proto);
1535
+ objWithOwn.own = 2;
1536
+ expect(toNonEmptyPlainObject(objWithOwn)).toBe(objWithOwn);
1537
+
1538
+ // Objects with symbol keys (symbols are not enumerated by for...in)
1539
+ const sym = Symbol("key");
1540
+ const objWithSymbol = { [sym]: 1 };
1541
+ expect(toNonEmptyPlainObject(objWithSymbol)).toBe(undefined);
1542
+
1543
+ // Objects with both string and symbol keys
1544
+ const objWithBoth = { a: 1, [sym]: 2 };
1545
+ expect(toNonEmptyPlainObject(objWithBoth)).toBe(objWithBoth);
1546
+
1547
+ // Objects with non-enumerable properties
1548
+ const objWithNonEnumerable = {};
1549
+ Object.defineProperty(objWithNonEnumerable, "hidden", { value: 1, enumerable: false });
1550
+ expect(toNonEmptyPlainObject(objWithNonEnumerable)).toBe(undefined);
1551
+
1552
+ // Object.create(null) with properties
1553
+ const nullProtoObj = Object.create(null);
1554
+ nullProtoObj.a = 1;
1555
+ expect(toNonEmptyPlainObject(nullProtoObj)).toBe(nullProtoObj);
1556
+
1557
+ // Empty Object.create(null)
1558
+ expect(toNonEmptyPlainObject(Object.create(null))).toBe(undefined);
1559
+
1560
+ // Class instances (they are plain objects in the shallow sense)
1561
+ class MyClass {
1562
+ prop = 1;
1563
+ }
1564
+ const instance = new MyClass();
1565
+ expect(toNonEmptyPlainObject(instance)).toBe(instance);
1566
+
1567
+ // Empty class instance
1568
+ class EmptyClass {}
1569
+ expect(toNonEmptyPlainObject(new EmptyClass())).toBe(undefined);
888
1570
 
889
1571
  {
890
1572
  // Type narrowing - preserves object type
@@ -893,6 +1575,8 @@ describe("primitive.ts", () => {
893
1575
  if (result) {
894
1576
  const check: { a: number } = result;
895
1577
  expect(check).toEqual({ a: 1 });
1578
+ } else {
1579
+ throw new Error("Unreachable");
896
1580
  }
897
1581
  }
898
1582
 
@@ -911,18 +1595,179 @@ describe("primitive.ts", () => {
911
1595
  }
912
1596
 
913
1597
  {
914
- // type narrowing - non-object type returns PlainObject | undefined
1598
+ // Type narrowing - non-object type returns PlainObject | undefined
915
1599
  const obj = castType<number>(42);
916
1600
  const result: PlainObject | undefined = toNonEmptyPlainObject(obj);
917
1601
  expect(result).toBe(undefined);
918
1602
  }
1603
+
1604
+ {
1605
+ // Type narrowing - unknown input returns PlainObject | undefined
1606
+ const obj = castType<unknown>({ a: 1 });
1607
+ const result: PlainObject | undefined = toNonEmptyPlainObject(obj);
1608
+ expect(result).toEqual({ a: 1 });
1609
+ }
1610
+
1611
+ {
1612
+ // Type narrowing - any input returns PlainObject | undefined
1613
+ const obj = castType<any>({ a: 1 });
1614
+ const result: PlainObject | undefined = toNonEmptyPlainObject(obj);
1615
+ expect(result).toEqual({ a: 1 });
1616
+ }
1617
+
1618
+ {
1619
+ // Type narrowing - extracts object from union with array
1620
+ const obj = castType<{ a: number } | number[]>({ a: 1 });
1621
+ const result = toNonEmptyPlainObject(obj);
1622
+ if (result) {
1623
+ const check: { a: number } = result;
1624
+ expect(check).toEqual({ a: 1 });
1625
+ }
1626
+ }
1627
+
1628
+ {
1629
+ // Type narrowing - array in union returns undefined
1630
+ const obj = castType<{ a: number } | number[]>([1, 2, 3]);
1631
+ const result = toNonEmptyPlainObject(obj);
1632
+ expect(result).toBe(undefined);
1633
+ }
1634
+
1635
+ {
1636
+ // Type narrowing - null | object union extracts PlainObject
1637
+ const obj = castType<null | { x: number }>({ x: 42 });
1638
+ const result = toNonEmptyPlainObject(obj);
1639
+ if (result) {
1640
+ const check: { x: number } = result;
1641
+ expect(check).toEqual({ x: 42 });
1642
+ }
1643
+ }
1644
+
1645
+ {
1646
+ // Type narrowing - null returns undefined
1647
+ const obj = castType<null | { x: number }>(null);
1648
+ const result = toNonEmptyPlainObject(obj);
1649
+ expect(result).toBe(undefined);
1650
+ }
1651
+
1652
+ {
1653
+ // Type narrowing - preserves complex object type
1654
+ const obj = castType<{ a: string; b: number; c: boolean }>({ a: "hello", b: 42, c: true });
1655
+ const result = toNonEmptyPlainObject(obj);
1656
+ if (result) {
1657
+ const check: { a: string; b: number; c: boolean } = result;
1658
+ expect(check).toEqual({ a: "hello", b: 42, c: true });
1659
+ }
1660
+ }
1661
+
1662
+ {
1663
+ // Type narrowing - optional chaining works
1664
+ const obj = castType<unknown>({ a: 1 });
1665
+ const keys = Object.keys(toNonEmptyPlainObject(obj) ?? {});
1666
+ expect(keys).toEqual(["a"]);
1667
+ }
919
1668
  });
920
1669
 
921
1670
  it("isNonEmptyJSONObject", () => {
1671
+ // Runtime behavior - truthy cases (has at least one non-undefined value)
922
1672
  expect(isNonEmptyJSONObject({ a: 1 })).toBe(true);
1673
+ expect(isNonEmptyJSONObject({ a: null })).toBe(true);
1674
+ expect(isNonEmptyJSONObject({ a: false })).toBe(true);
1675
+ expect(isNonEmptyJSONObject({ a: 0 })).toBe(true);
1676
+ expect(isNonEmptyJSONObject({ a: "" })).toBe(true);
1677
+ expect(isNonEmptyJSONObject({ "": 1 })).toBe(true);
1678
+ expect(isNonEmptyJSONObject({ 0: "a" })).toBe(true);
1679
+ expect(isNonEmptyJSONObject({ a: 1, b: 2, c: 3 })).toBe(true);
1680
+ expect(isNonEmptyJSONObject({ nested: { deep: { value: 1 } } })).toBe(true);
1681
+ expect(isNonEmptyJSONObject(Object.create(null, { a: { value: 1, enumerable: true } }))).toBe(true);
1682
+ // Mixed undefined and defined values - should be true
1683
+ expect(isNonEmptyJSONObject({ a: undefined, b: 1 })).toBe(true);
1684
+ expect(isNonEmptyJSONObject({ a: 1, b: undefined })).toBe(true);
1685
+ expect(isNonEmptyJSONObject({ a: undefined, b: undefined, c: null })).toBe(true);
1686
+
1687
+ // Runtime behavior - falsy cases
923
1688
  expect(isNonEmptyJSONObject({})).toBe(false);
924
- expect(isNonEmptyJSONObject([])).toBe(false);
925
1689
  expect(isNonEmptyJSONObject({ a: undefined })).toBe(false);
1690
+ expect(isNonEmptyJSONObject({ a: undefined, b: undefined })).toBe(false);
1691
+ expect(isNonEmptyJSONObject([])).toBe(false);
1692
+ expect(isNonEmptyJSONObject([1, 2, 3])).toBe(false);
1693
+ expect(isNonEmptyJSONObject("hello")).toBe(false);
1694
+ expect(isNonEmptyJSONObject("")).toBe(false);
1695
+ expect(isNonEmptyJSONObject(1)).toBe(false);
1696
+ expect(isNonEmptyJSONObject(0)).toBe(false);
1697
+ expect(isNonEmptyJSONObject(NaN)).toBe(false);
1698
+ expect(isNonEmptyJSONObject(null)).toBe(false);
1699
+ expect(isNonEmptyJSONObject(undefined)).toBe(false);
1700
+ expect(isNonEmptyJSONObject(false)).toBe(false);
1701
+ expect(isNonEmptyJSONObject(true)).toBe(false);
1702
+ expect(isNonEmptyJSONObject(Symbol())).toBe(false);
1703
+ expect(isNonEmptyJSONObject(() => {})).toBe(false);
1704
+ expect(isNonEmptyJSONObject(function () {})).toBe(false);
1705
+ expect(isNonEmptyJSONObject(new Date())).toBe(false);
1706
+ expect(isNonEmptyJSONObject(/regex/)).toBe(false);
1707
+ expect(isNonEmptyJSONObject(new Map([["a", 1]]))).toBe(false);
1708
+ expect(isNonEmptyJSONObject(new Set([1, 2]))).toBe(false);
1709
+
1710
+ // Objects with only inherited properties (no own properties)
1711
+ const proto = { inherited: 1 };
1712
+ const objWithInherited = Object.create(proto);
1713
+ expect(isNonEmptyJSONObject(objWithInherited)).toBe(false);
1714
+
1715
+ // Objects with inherited and own undefined property
1716
+ const objWithOwnUndefined = Object.create(proto);
1717
+ objWithOwnUndefined.own = undefined;
1718
+ expect(isNonEmptyJSONObject(objWithOwnUndefined)).toBe(false);
1719
+
1720
+ // Objects with own non-undefined property
1721
+ const objWithOwn = Object.create(proto);
1722
+ objWithOwn.own = 2;
1723
+ expect(isNonEmptyJSONObject(objWithOwn)).toBe(true);
1724
+
1725
+ // Objects with symbol keys (symbols are not enumerated by for...in)
1726
+ const sym = Symbol("key");
1727
+ const objWithSymbol = { [sym]: 1 };
1728
+ expect(isNonEmptyJSONObject(objWithSymbol)).toBe(false);
1729
+
1730
+ // Objects with both string and symbol keys
1731
+ const objWithBoth = { a: 1, [sym]: 2 };
1732
+ expect(isNonEmptyJSONObject(objWithBoth)).toBe(true);
1733
+
1734
+ // Objects with symbol key and only undefined string key
1735
+ const objWithSymbolAndUndefined = { a: undefined, [sym]: 2 };
1736
+ expect(isNonEmptyJSONObject(objWithSymbolAndUndefined)).toBe(false);
1737
+
1738
+ // Objects with non-enumerable properties
1739
+ const objWithNonEnumerable = {};
1740
+ Object.defineProperty(objWithNonEnumerable, "hidden", { value: 1, enumerable: false });
1741
+ expect(isNonEmptyJSONObject(objWithNonEnumerable)).toBe(false);
1742
+
1743
+ // Object.create(null) with non-undefined property
1744
+ const nullProtoObj = Object.create(null);
1745
+ nullProtoObj.a = 1;
1746
+ expect(isNonEmptyJSONObject(nullProtoObj)).toBe(true);
1747
+
1748
+ // Object.create(null) with only undefined property
1749
+ const nullProtoObjUndefined = Object.create(null);
1750
+ nullProtoObjUndefined.a = undefined;
1751
+ expect(isNonEmptyJSONObject(nullProtoObjUndefined)).toBe(false);
1752
+
1753
+ // Empty Object.create(null)
1754
+ expect(isNonEmptyJSONObject(Object.create(null))).toBe(false);
1755
+
1756
+ // Class instances with non-undefined property
1757
+ class MyClass {
1758
+ prop = 1;
1759
+ }
1760
+ expect(isNonEmptyJSONObject(new MyClass())).toBe(true);
1761
+
1762
+ // Class instances with only undefined property
1763
+ class MyClassUndefined {
1764
+ prop = undefined;
1765
+ }
1766
+ expect(isNonEmptyJSONObject(new MyClassUndefined())).toBe(false);
1767
+
1768
+ // Empty class instance
1769
+ class EmptyClass {}
1770
+ expect(isNonEmptyJSONObject(new EmptyClass())).toBe(false);
926
1771
 
927
1772
  {
928
1773
  // Type narrowing - unknown input narrows to PlainObject
@@ -930,6 +1775,8 @@ describe("primitive.ts", () => {
930
1775
  if (isNonEmptyJSONObject(obj)) {
931
1776
  const check: PlainObject = obj;
932
1777
  expect(check).toEqual({ a: 1 });
1778
+ } else {
1779
+ throw new Error("Unreachable");
933
1780
  }
934
1781
  }
935
1782
 
@@ -937,8 +1784,8 @@ describe("primitive.ts", () => {
937
1784
  // Type narrowing - object with only undefined values returns false
938
1785
  const obj = castType<{ a?: number }>({ a: undefined });
939
1786
  if (isNonEmptyJSONObject(obj)) {
940
- const check: PlainObject = obj;
941
- expect(check).toEqual({});
1787
+ const _check: { a?: number } = obj;
1788
+ throw new Error("Unreachable");
942
1789
  } else {
943
1790
  expect(obj).toEqual({ a: undefined });
944
1791
  }
@@ -947,16 +1794,182 @@ describe("primitive.ts", () => {
947
1794
  {
948
1795
  // Type narrowing - excludes array
949
1796
  const obj = castType<{ a: number } | number[]>({ a: 1 });
1797
+ if (isNonEmptyJSONObject(obj)) {
1798
+ const check: { a: number } = obj;
1799
+ expect(check).toEqual({ a: 1 });
1800
+ } else {
1801
+ const _check: number[] = obj;
1802
+ throw new Error("Unreachable");
1803
+ }
1804
+ }
1805
+
1806
+ {
1807
+ // Type narrowing - array returns false
1808
+ const arr = castType<{ a: number } | number[]>([1, 2, 3]);
1809
+ if (isNonEmptyJSONObject(arr)) {
1810
+ const _check: { a: number } = arr;
1811
+ throw new Error("Unreachable");
1812
+ } else {
1813
+ const check: number[] = arr;
1814
+ expect(check).toEqual([1, 2, 3]);
1815
+ }
1816
+ }
1817
+
1818
+ {
1819
+ // Type narrowing - null | object union extracts PlainObject
1820
+ const obj = castType<null | { x: number }>({ x: 42 });
1821
+ if (isNonEmptyJSONObject(obj)) {
1822
+ const check: { x: number } = obj;
1823
+ expect(check).toEqual({ x: 42 });
1824
+ } else {
1825
+ const _check: null = obj;
1826
+ throw new Error("Unreachable");
1827
+ }
1828
+ }
1829
+
1830
+ {
1831
+ // Type narrowing - null returns false
1832
+ const obj = castType<null | { x: number }>(null);
1833
+ if (isNonEmptyJSONObject(obj)) {
1834
+ const _check: { x: number } = obj;
1835
+ throw new Error("Unreachable");
1836
+ } else {
1837
+ const check: null = obj;
1838
+ expect(check).toBe(null);
1839
+ }
1840
+ }
1841
+
1842
+ {
1843
+ // Type narrowing - preserves object type
1844
+ const obj = castType<{ a: string; b: number }>({ a: "hello", b: 42 });
1845
+ if (isNonEmptyJSONObject(obj)) {
1846
+ const check: { a: string; b: number } = obj;
1847
+ expect(check).toEqual({ a: "hello", b: 42 });
1848
+ } else {
1849
+ throw new Error("Unreachable");
1850
+ }
1851
+ }
1852
+
1853
+ {
1854
+ // Type narrowing - any input
1855
+ const obj = castType<any>({ a: 1 });
950
1856
  if (isNonEmptyJSONObject(obj)) {
951
1857
  const check: PlainObject = obj;
952
1858
  expect(check).toEqual({ a: 1 });
953
1859
  }
954
1860
  }
1861
+
1862
+ {
1863
+ // Type narrowing - generic function
1864
+ const _fn = <T>(x: T): void => {
1865
+ if (isNonEmptyJSONObject(x)) {
1866
+ const y: object = x;
1867
+ expect(typeof y).toBe("object");
1868
+ }
1869
+ };
1870
+ }
955
1871
  });
956
1872
 
957
1873
  it("toNonEmptyJSONObject", () => {
1874
+ // Runtime behavior - returns value for objects with at least one non-undefined value
958
1875
  expect(toNonEmptyJSONObject({ a: 1 })).toEqual({ a: 1 });
1876
+ expect(toNonEmptyJSONObject({ a: null })).toEqual({ a: null });
1877
+ expect(toNonEmptyJSONObject({ a: false })).toEqual({ a: false });
1878
+ expect(toNonEmptyJSONObject({ a: 0 })).toEqual({ a: 0 });
1879
+ expect(toNonEmptyJSONObject({ a: "" })).toEqual({ a: "" });
1880
+ expect(toNonEmptyJSONObject({ "": 1 })).toEqual({ "": 1 });
1881
+ expect(toNonEmptyJSONObject({ 0: "a" })).toEqual({ 0: "a" });
1882
+ expect(toNonEmptyJSONObject({ a: 1, b: 2, c: 3 })).toEqual({ a: 1, b: 2, c: 3 });
1883
+ expect(toNonEmptyJSONObject({ nested: { deep: { value: 1 } } })).toEqual({ nested: { deep: { value: 1 } } });
1884
+ // Mixed undefined and defined values - should return the object
1885
+ expect(toNonEmptyJSONObject({ a: undefined, b: 1 })).toEqual({ a: undefined, b: 1 });
1886
+ expect(toNonEmptyJSONObject({ a: 1, b: undefined })).toEqual({ a: 1, b: undefined });
1887
+
1888
+ // Runtime behavior - returns undefined for empty or non-objects or all-undefined
959
1889
  expect(toNonEmptyJSONObject({})).toBe(undefined);
1890
+ expect(toNonEmptyJSONObject({ a: undefined })).toBe(undefined);
1891
+ expect(toNonEmptyJSONObject({ a: undefined, b: undefined })).toBe(undefined);
1892
+ expect(toNonEmptyJSONObject([])).toBe(undefined);
1893
+ expect(toNonEmptyJSONObject([1, 2, 3])).toBe(undefined);
1894
+ expect(toNonEmptyJSONObject("hello")).toBe(undefined);
1895
+ expect(toNonEmptyJSONObject("")).toBe(undefined);
1896
+ expect(toNonEmptyJSONObject(1)).toBe(undefined);
1897
+ expect(toNonEmptyJSONObject(0)).toBe(undefined);
1898
+ expect(toNonEmptyJSONObject(NaN)).toBe(undefined);
1899
+ expect(toNonEmptyJSONObject(null)).toBe(undefined);
1900
+ expect(toNonEmptyJSONObject(undefined)).toBe(undefined);
1901
+ expect(toNonEmptyJSONObject(false)).toBe(undefined);
1902
+ expect(toNonEmptyJSONObject(true)).toBe(undefined);
1903
+ expect(toNonEmptyJSONObject(Symbol())).toBe(undefined);
1904
+ expect(toNonEmptyJSONObject(() => {})).toBe(undefined);
1905
+ expect(toNonEmptyJSONObject(function () {})).toBe(undefined);
1906
+ expect(toNonEmptyJSONObject(new Date())).toBe(undefined);
1907
+ expect(toNonEmptyJSONObject(/regex/)).toBe(undefined);
1908
+ expect(toNonEmptyJSONObject(new Map([["a", 1]]))).toBe(undefined);
1909
+ expect(toNonEmptyJSONObject(new Set([1, 2]))).toBe(undefined);
1910
+
1911
+ // Objects with only inherited properties (no own properties)
1912
+ const proto = { inherited: 1 };
1913
+ const objWithInherited = Object.create(proto);
1914
+ expect(toNonEmptyJSONObject(objWithInherited)).toBe(undefined);
1915
+
1916
+ // Objects with inherited and own undefined property
1917
+ const objWithOwnUndefined = Object.create(proto);
1918
+ objWithOwnUndefined.own = undefined;
1919
+ expect(toNonEmptyJSONObject(objWithOwnUndefined)).toBe(undefined);
1920
+
1921
+ // Objects with own non-undefined property
1922
+ const objWithOwn = Object.create(proto);
1923
+ objWithOwn.own = 2;
1924
+ expect(toNonEmptyJSONObject(objWithOwn)).toBe(objWithOwn);
1925
+
1926
+ // Objects with symbol keys (symbols are not enumerated by for...in)
1927
+ const sym = Symbol("key");
1928
+ const objWithSymbol = { [sym]: 1 };
1929
+ expect(toNonEmptyJSONObject(objWithSymbol)).toBe(undefined);
1930
+
1931
+ // Objects with both string and symbol keys
1932
+ const objWithBoth = { a: 1, [sym]: 2 };
1933
+ expect(toNonEmptyJSONObject(objWithBoth)).toBe(objWithBoth);
1934
+
1935
+ // Objects with symbol key and only undefined string key
1936
+ const objWithSymbolAndUndefined = { a: undefined, [sym]: 2 };
1937
+ expect(toNonEmptyJSONObject(objWithSymbolAndUndefined)).toBe(undefined);
1938
+
1939
+ // Objects with non-enumerable properties
1940
+ const objWithNonEnumerable = {};
1941
+ Object.defineProperty(objWithNonEnumerable, "hidden", { value: 1, enumerable: false });
1942
+ expect(toNonEmptyJSONObject(objWithNonEnumerable)).toBe(undefined);
1943
+
1944
+ // Object.create(null) with non-undefined property
1945
+ const nullProtoObj = Object.create(null);
1946
+ nullProtoObj.a = 1;
1947
+ expect(toNonEmptyJSONObject(nullProtoObj)).toBe(nullProtoObj);
1948
+
1949
+ // Object.create(null) with only undefined property
1950
+ const nullProtoObjUndefined = Object.create(null);
1951
+ nullProtoObjUndefined.a = undefined;
1952
+ expect(toNonEmptyJSONObject(nullProtoObjUndefined)).toBe(undefined);
1953
+
1954
+ // Empty Object.create(null)
1955
+ expect(toNonEmptyJSONObject(Object.create(null))).toBe(undefined);
1956
+
1957
+ // Class instances with non-undefined property
1958
+ class MyClass {
1959
+ prop = 1;
1960
+ }
1961
+ const instance = new MyClass();
1962
+ expect(toNonEmptyJSONObject(instance)).toBe(instance);
1963
+
1964
+ // Class instances with only undefined property
1965
+ class MyClassUndefined {
1966
+ prop = undefined;
1967
+ }
1968
+ expect(toNonEmptyJSONObject(new MyClassUndefined())).toBe(undefined);
1969
+
1970
+ // Empty class instance
1971
+ class EmptyClass {}
1972
+ expect(toNonEmptyJSONObject(new EmptyClass())).toBe(undefined);
960
1973
 
961
1974
  {
962
1975
  // Type narrowing - preserves object type
@@ -965,6 +1978,8 @@ describe("primitive.ts", () => {
965
1978
  if (result) {
966
1979
  const check: { a: number } = result;
967
1980
  expect(check).toEqual({ a: 1 });
1981
+ } else {
1982
+ throw new Error("Unreachable");
968
1983
  }
969
1984
  }
970
1985
 
@@ -981,6 +1996,78 @@ describe("primitive.ts", () => {
981
1996
  const result = toNonEmptyJSONObject(obj);
982
1997
  expect(result).toBe(undefined);
983
1998
  }
1999
+
2000
+ {
2001
+ // Type narrowing - non-object type returns PlainObject | undefined
2002
+ const obj = castType<number>(42);
2003
+ const result: PlainObject | undefined = toNonEmptyJSONObject(obj);
2004
+ expect(result).toBe(undefined);
2005
+ }
2006
+
2007
+ {
2008
+ // Type narrowing - unknown input returns PlainObject | undefined
2009
+ const obj = castType<unknown>({ a: 1 });
2010
+ const result: PlainObject | undefined = toNonEmptyJSONObject(obj);
2011
+ expect(result).toEqual({ a: 1 });
2012
+ }
2013
+
2014
+ {
2015
+ // Type narrowing - any input returns PlainObject | undefined
2016
+ const obj = castType<any>({ a: 1 });
2017
+ const result: PlainObject | undefined = toNonEmptyJSONObject(obj);
2018
+ expect(result).toEqual({ a: 1 });
2019
+ }
2020
+
2021
+ {
2022
+ // Type narrowing - extracts object from union with array
2023
+ const obj = castType<{ a: number } | number[]>({ a: 1 });
2024
+ const result = toNonEmptyJSONObject(obj);
2025
+ if (result) {
2026
+ const check: { a: number } = result;
2027
+ expect(check).toEqual({ a: 1 });
2028
+ }
2029
+ }
2030
+
2031
+ {
2032
+ // Type narrowing - array in union returns undefined
2033
+ const obj = castType<{ a: number } | number[]>([1, 2, 3]);
2034
+ const result = toNonEmptyJSONObject(obj);
2035
+ expect(result).toBe(undefined);
2036
+ }
2037
+
2038
+ {
2039
+ // Type narrowing - null | object union extracts PlainObject
2040
+ const obj = castType<null | { x: number }>({ x: 42 });
2041
+ const result = toNonEmptyJSONObject(obj);
2042
+ if (result) {
2043
+ const check: { x: number } = result;
2044
+ expect(check).toEqual({ x: 42 });
2045
+ }
2046
+ }
2047
+
2048
+ {
2049
+ // Type narrowing - null returns undefined
2050
+ const obj = castType<null | { x: number }>(null);
2051
+ const result = toNonEmptyJSONObject(obj);
2052
+ expect(result).toBe(undefined);
2053
+ }
2054
+
2055
+ {
2056
+ // Type narrowing - preserves complex object type
2057
+ const obj = castType<{ a: string; b: number; c: boolean }>({ a: "hello", b: 42, c: true });
2058
+ const result = toNonEmptyJSONObject(obj);
2059
+ if (result) {
2060
+ const check: { a: string; b: number; c: boolean } = result;
2061
+ expect(check).toEqual({ a: "hello", b: 42, c: true });
2062
+ }
2063
+ }
2064
+
2065
+ {
2066
+ // Type narrowing - optional chaining works
2067
+ const obj = castType<unknown>({ a: 1 });
2068
+ const keys = Object.keys(toNonEmptyJSONObject(obj) ?? {});
2069
+ expect(keys).toEqual(["a"]);
2070
+ }
984
2071
  });
985
2072
 
986
2073
  it("toPlainObjectOf", () => {
package/src/is-to-as.ts CHANGED
@@ -5,7 +5,7 @@ export type _ = undefined;
5
5
  export type SetDefaultType<T, U> = [T, U][T extends any ? (0 extends 1 & T ? 1 : 0) : 1];
6
6
 
7
7
  /** Returns `true` if `x` is not `undefined`. */
8
- export const isDefined = <T>(x: T | undefined): x is T => x !== _;
8
+ export const isDefined = <T>(x: T | _): x is Exclude<T, _> => x !== _;
9
9
 
10
10
  export const isTrue = (x: unknown): x is true => x === true;
11
11