@wopjs/cast 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,14 @@
6
6
  [![Coverage Status](https://wopjs.github.io/cast/coverage-badges/@wopjs/cast.svg)](https://wopjs.github.io/cast/coverage/)
7
7
  [![minified-size](https://img.shields.io/bundlephobia/minzip/@wopjs/cast)](https://bundlephobia.com/package/@wopjs/cast)
8
8
 
9
- Filter types from unknown.
9
+ Type-safe utilities for filtering and coercing `unknown` values in TypeScript.
10
+
11
+ ## Features
12
+
13
+ - **Three-tier API pattern** (`is`/`to`/`as`) for flexible type filtering
14
+ - **Strong TypeScript type narrowing** that preserves complex types (unions, tuples, readonly arrays)
15
+ - **Zero dependencies** and tree-shakeable
16
+ - **Safe edge case handling** (NaN, null, undefined, circular references)
10
17
 
11
18
  ## Install
12
19
 
@@ -14,22 +21,153 @@ Filter types from unknown.
14
21
  npm add @wopjs/cast
15
22
  ```
16
23
 
17
- ## Usage
24
+ ## API Pattern
18
25
 
19
- ```js
20
- import * as c from "@wopjs/cast";
21
- import { Option } from "@wopjs/tsur";
26
+ Every type has up to three functions following a consistent naming pattern:
27
+
28
+ | Pattern | Returns | Use Case |
29
+ | ------- | ---------------- | --------------------------------------------- |
30
+ | `is*` | `boolean` | Type guards for conditional narrowing |
31
+ | `to*` | `T \| undefined` | Optional values, composable with Option types |
32
+ | `as*` | `T` | Always returns valid value with fallback |
33
+
34
+ ```ts
35
+ import { isNumber, toNumber, asNumber } from "@wopjs/cast";
36
+
37
+ // is* - Type guard for conditionals
38
+ if (isNumber(value)) {
39
+ value; // type narrowed to number
40
+ }
41
+
42
+ // to* - Returns undefined for invalid input
43
+ const num = toNumber(input); // number | undefined
44
+
45
+ // as* - Always returns a number (0 as fallback)
46
+ const safeNum = asNumber(input); // number
47
+ ```
48
+
49
+ ## Type Narrowing
50
+
51
+ The library preserves and correctly narrows complex TypeScript types:
52
+
53
+ ```ts
54
+ import { isArray, toArray, isTruthy } from "@wopjs/cast";
55
+
56
+ // Preserves array element types
57
+ const arr: string[] = ["a", "b"];
58
+ if (isArray(arr)) {
59
+ arr; // still string[], not unknown[]
60
+ }
61
+
62
+ // Extracts from unions
63
+ const value: string | string[] = getData();
64
+ if (isArray(value)) {
65
+ value; // narrowed to string[]
66
+ }
67
+
68
+ // Preserves tuples and readonly arrays
69
+ const tuple: [string, number] = ["a", 1];
70
+ const result = toArray(tuple); // [string, number] | undefined
71
+
72
+ // Excludes falsy types
73
+ const val: string | null | undefined = "hello";
74
+ if (isTruthy(val)) {
75
+ val; // narrowed to string
76
+ }
77
+ ```
78
+
79
+ ## Available Functions
80
+
81
+ ### Booleans
82
+
83
+ | Function | Description |
84
+ | ----------- | -------------------------------------------- |
85
+ | `isTrue` | Returns `true` if value is exactly `true` |
86
+ | `toTrue` | Returns `true` or `undefined` |
87
+ | `asTrue` | Returns `true` or `false` |
88
+ | `isTruthy` | Returns `true` if `Boolean(x)` is `true` |
89
+ | `toTruthy` | Returns truthy value or `undefined` |
90
+ | `isFalsy` | Returns `true` if `Boolean(x)` is `false` |
91
+ | `toFalsy` | Returns falsy value or `undefined` |
92
+ | `isBoolean` | Returns `true` if value is `true` or `false` |
93
+ | `toBoolean` | Returns boolean or `undefined` |
94
+
95
+ ### Numbers
96
+
97
+ | Function | Description |
98
+ | ---------- | ----------------------------------------------------- |
99
+ | `isNumber` | Returns `true` if value is a number (excluding `NaN`) |
100
+ | `toNumber` | Returns number or `undefined` |
101
+ | `asNumber` | Returns number or `0` |
102
+
103
+ ### Strings
104
+
105
+ | Function | Description |
106
+ | ------------------ | --------------------------------------------- |
107
+ | `isString` | Returns `true` if value is a string |
108
+ | `toString` | Returns string or `undefined` |
109
+ | `asString` | Returns string or `""` |
110
+ | `isNonEmptyString` | Returns `true` if value is a non-empty string |
111
+ | `toNonEmptyString` | Returns non-empty string or `undefined` |
112
+
113
+ ### Arrays
22
114
 
23
- const dataParser = {
24
- width: c.toNumber,
25
- position: a => Option.from(a, a => a && c.isNumber(a.x) && c.isNumber(a.y)),
26
- metadata: c.toNonEmptyPlainObject,
27
- };
115
+ | Function | Description |
116
+ | ----------------- | ----------------------------------------------- |
117
+ | `isArray` | Type guard for arrays (preserves element types) |
118
+ | `toArray` | Returns array or `undefined` |
119
+ | `asArray` | Returns array or `[]` |
120
+ | `isNonEmptyArray` | Type guard for non-empty arrays |
121
+ | `toNonEmptyArray` | Returns non-empty array or `undefined` |
28
122
 
29
- function parseData(data) {
30
- const d = c.asObject(data);
31
- return Object.fromEntries(Object.keys(dataParser).map(k => [k, Option.unwrapOr(dataParser[k](d[k]))]));
123
+ ### Objects
124
+
125
+ | Function | Description |
126
+ | ----------------------- | --------------------------------------------------------------- |
127
+ | `isObject` | Returns `true` for objects (including arrays, excluding `null`) |
128
+ | `toObject` | Returns object or `undefined` |
129
+ | `asObject` | Returns object or `{}` |
130
+ | `isPlainObject` | Returns `true` for plain objects (excluding arrays) |
131
+ | `toPlainObject` | Returns plain object or `undefined` |
132
+ | `asPlainObject` | Returns plain object or `{}` |
133
+ | `isNonEmptyPlainObject` | Returns `true` for objects with at least one key |
134
+ | `toNonEmptyPlainObject` | Returns non-empty object or `undefined` |
135
+ | `isNonEmptyJSONObject` | Returns `true` for objects with non-undefined values |
136
+ | `toNonEmptyJSONObject` | Returns JSON object or `undefined` |
137
+
138
+ ### Utilities
139
+
140
+ | Function | Description |
141
+ | --------------------- | ------------------------------------------ |
142
+ | `isDefined` | Returns `true` if value is not `undefined` |
143
+ | `toPlainObjectOf` | Filter object values by type predicate |
144
+ | `toPlainObjectOfTrue` | Filter object to only `true` values |
145
+ | `print` | Safely stringify any value for display |
146
+
147
+ ## Usage Example
148
+
149
+ ```ts
150
+ import * as c from "@wopjs/cast";
151
+
152
+ // Parsing unknown API response
153
+ function parseUser(data: unknown) {
154
+ const obj = c.asPlainObject(data);
155
+ return {
156
+ name: c.asString(obj.name),
157
+ age: c.toNumber(obj.age), // undefined if not a number
158
+ tags: c.asArray(obj.tags),
159
+ settings: c.toNonEmptyPlainObject(obj.settings),
160
+ };
32
161
  }
162
+
163
+ // Filtering object values
164
+ const config = { debug: true, verbose: false, enabled: true };
165
+ c.toPlainObjectOfTrue(config); // { debug: true, enabled: true }
166
+
167
+ // Safe number handling
168
+ c.isNumber(NaN); // false (NaN is excluded)
169
+ c.asNumber(NaN); // 0 (safe fallback)
170
+ c.asNumber("42"); // 0 (not coerced, use parseInt for that)
33
171
  ```
34
172
 
35
173
  ## Publish New Version
package/dist/index.d.mts CHANGED
@@ -1,4 +1,6 @@
1
1
  type _ = undefined;
2
+ /** Returns `U` if `T` is `never` or `any`, otherwise returns `T`. */
3
+ type SetDefaultType<T, U> = [T, U][T extends any ? (0 extends 1 & T ? 1 : 0) : 1];
2
4
  /** Returns `true` if `x` is not `undefined`. */
3
5
  declare const isDefined: <T>(x: T | undefined) => x is T;
4
6
  declare const isTrue: (x: unknown) => x is true;
@@ -7,12 +9,11 @@ declare const toTrue: (x: unknown) => true | _;
7
9
  /** Returns `true` if `x` is `true`, otherwise returns `false`. */
8
10
  declare const asTrue: (x: unknown) => boolean;
9
11
  type Falsy = false | null | undefined | 0 | "";
10
- interface IsFalsy {
11
- (x: unknown): x is Falsy;
12
- <T>(x: T): x is Extract<T, Falsy>;
13
- }
12
+ type ExtractFalsy<T> = SetDefaultType<Extract<T, Falsy>, Falsy>;
14
13
  /** Returns `true` if `Boolean(x)` is `false`. */
15
- declare const isFalsy: IsFalsy;
14
+ declare const isFalsy: <T>(x: T) => x is ExtractFalsy<T>;
15
+ /** Returns `x` if `Boolean(x)` is `false`, otherwise returns `undefined`. */
16
+ declare const toFalsy: <T>(x: T) => ExtractFalsy<T> | _;
16
17
  /** Returns `true` if `Boolean(x)` is `true`. */
17
18
  declare const isTruthy: <T>(x: T) => x is Exclude<T, Falsy>;
18
19
  /** Returns `x` if `Boolean(x)` is `true`, otherwise returns `undefined`. */
@@ -36,53 +37,49 @@ declare const asString: (x: unknown) => string;
36
37
  declare const isNonEmptyString: (x: unknown) => x is string;
37
38
  /** Returns `x` if `x` is a string and not empty, otherwise returns `undefined`. */
38
39
  declare const toNonEmptyString: (x: unknown) => string | _;
39
- type NormalizeArrayType<T> = T extends readonly unknown[] ? T : unknown[];
40
- type ExtractArray<T> = NormalizeArrayType<Extract<T, readonly unknown[]>>;
41
- interface IsArray {
42
- (x: unknown): x is unknown[];
43
- <T>(x: T): x is T extends readonly unknown[] ? T : never;
44
- }
45
- declare const isArray: IsArray;
40
+ type ExtractArray<T> = SetDefaultType<Extract<T, readonly unknown[]>, unknown[]>;
41
+ declare const isArray: <T>(x: T) => x is ExtractArray<T>;
46
42
  /** Returns `x` if `x` is an array. */
47
43
  declare const toArray: <T>(x: T) => ExtractArray<T> | _;
44
+ /** Returns `x` if `x` is an array, otherwise returns `[]` (empty array). */
45
+ declare const asArray: <T>(x: T) => ExtractArray<T>;
48
46
  /** Returns `true` if `x` is an array and has at least one element. */
49
- declare const isNonEmptyArray: IsArray;
47
+ declare const isNonEmptyArray: <T>(x: T) => x is ExtractArray<T>;
50
48
  /** Returns `x` if `x` is an array and has at least one element, otherwise returns `undefined`. */
51
49
  declare const toNonEmptyArray: <T>(x: T) => ExtractArray<T> | _;
52
- /** Returns `x` if `x` is an array, otherwise returns `[]` (empty array). */
53
- declare const asArray: <T>(x: T) => ExtractArray<T>;
50
+ type ExtractObject<T> = SetDefaultType<Extract<T, object>, object>;
51
+ /** Returns `true` if `x` is an object (including array) and not null. */
52
+ declare const isObject: <T>(x: T) => x is ExtractObject<T>;
53
+ /** Returns `x` if `x` is an object (including array). */
54
+ declare const toObject: <T>(x: T) => ExtractObject<T> | _;
55
+ /** Returns `x` if `x` is an object (including array), otherwise returns `{}` (empty object). */
56
+ declare const asObject: <T>(x: T) => ExtractObject<T>;
54
57
  interface PlainObject {
55
58
  [key: PropertyKey]: unknown;
56
59
  }
57
- /** Returns `true` if `x` is an object (including array) and not null. */
58
- declare const isObject: (x: unknown) => x is object;
59
- /** Returns `x` if `x` is an object (including array), otherwise returns `{}` (empty object). */
60
- declare const asObject: (x: unknown) => object;
60
+ type ExtractPlainObject<T> = SetDefaultType<Exclude<Extract<T, object>, readonly unknown[]>, PlainObject>;
61
61
  /** Returns `true` if `x` is a plain object (shallow test), not `null` or array. */
62
- declare const isPlainObject: (x: unknown) => x is PlainObject;
62
+ declare const isPlainObject: <T>(x: T) => x is ExtractPlainObject<T>;
63
63
  /** Returns `x` if `x` is a plain object. */
64
- declare const toPlainObject: (x: unknown) => PlainObject | _;
64
+ declare const toPlainObject: <T>(x: T) => ExtractPlainObject<T> | _;
65
65
  /** Returns `x` if `x` is a plain object, otherwise returns `{}` (empty object). */
66
- declare const asPlainObject: (x: unknown) => PlainObject;
66
+ declare const asPlainObject: <T>(x: T) => ExtractPlainObject<T>;
67
67
  /** Returns `true` if `x` is a plain object and has at least one key. */
68
- declare const isNonEmptyPlainObject: (x: unknown) => x is PlainObject;
68
+ declare const isNonEmptyPlainObject: <T>(x: T) => x is ExtractPlainObject<T>;
69
69
  /** Returns `x` if `x` is a plain object and has at least one key. */
70
- declare const toNonEmptyPlainObject: <T extends PlainObject>(x: T) => T | _;
70
+ declare const toNonEmptyPlainObject: <T>(x: T) => ExtractPlainObject<T> | _;
71
71
  /** Returns `true` if `x` is a plain object and has at least one key with non-undefined value. */
72
- declare const isNonEmptyJSONObject: (x: unknown) => x is PlainObject;
72
+ declare const isNonEmptyJSONObject: <T>(x: T) => x is ExtractPlainObject<T>;
73
73
  /** Returns `x` if `x` is a plain object and has at least one key with non-undefined value, otherwise returns `undefined`. */
74
- declare const toNonEmptyJSONObject: <T extends PlainObject>(x: T) => T | _;
74
+ declare const toNonEmptyJSONObject: <T>(x: T) => ExtractPlainObject<T> | _;
75
+ type ExtractPlainObjectValue<T> = ExtractPlainObject<T>[keyof ExtractPlainObject<T>];
75
76
  /**
76
77
  * Creates an object from `x` with keys `k` if `f(x[k])` returns `true`.
77
78
  * If `x` is not a plain object, or there's no passed props, returns `undefined`.
78
79
  */
79
- declare const toPlainObjectOf: <T>(x: unknown, f: (v: unknown) => v is T) => {
80
- [key: PropertyKey]: T;
81
- } | _;
80
+ declare const toPlainObjectOf: <T, U extends ExtractPlainObjectValue<T>>(x: T, f: (v: ExtractPlainObjectValue<T>) => v is U) => Record<PropertyKey, U> | _;
82
81
  /** Filter props from object `x` whose values are `true`. */
83
- declare const toPlainObjectOfTrue: (x: unknown) => {
84
- [key: PropertyKey]: true;
85
- } | _;
82
+ declare const toPlainObjectOfTrue: (x: unknown) => Record<PropertyKey, true> | _;
86
83
  /**
87
84
  * Returns `x` if `x` is string, otherwise returns `''` (empty string) if
88
85
  * `x` is `null` or `undefined`, otherwise returns `JSON.stringify(x)`.
@@ -97,4 +94,4 @@ declare const returnsFalse: () => false;
97
94
  declare const returnsTrue: () => true;
98
95
  declare const returnsEmptyString: () => string;
99
96
 
100
- export { type ExtractArray, type Falsy, type IsArray, type IsFalsy, type NormalizeArrayType, type PlainObject, type _, asArray, asNumber, asObject, asPlainObject, asString, asTrue, isArray, isBoolean, isDefined, isFalsy, isNonEmptyArray, isNonEmptyJSONObject, isNonEmptyPlainObject, isNonEmptyString, isNumber, isObject, isPlainObject, isString, isTrue, isTruthy, noop, print, returnsEmptyString, returnsFalse, returnsNull, returnsTrue, returnsUndefined, toArray, toBoolean, toNonEmptyArray, toNonEmptyJSONObject, toNonEmptyPlainObject, toNonEmptyString, toNumber, toPlainObject, toPlainObjectOf, toPlainObjectOfTrue, toString, toTrue, toTruthy };
97
+ export { type ExtractArray, type ExtractFalsy, type ExtractObject, type ExtractPlainObject, type Falsy, type PlainObject, type SetDefaultType, type _, asArray, asNumber, asObject, asPlainObject, asString, asTrue, isArray, isBoolean, isDefined, isFalsy, isNonEmptyArray, isNonEmptyJSONObject, isNonEmptyPlainObject, isNonEmptyString, isNumber, isObject, isPlainObject, isString, isTrue, isTruthy, noop, print, returnsEmptyString, returnsFalse, returnsNull, returnsTrue, returnsUndefined, toArray, toBoolean, toFalsy, toNonEmptyArray, toNonEmptyJSONObject, toNonEmptyPlainObject, toNonEmptyString, toNumber, toObject, toPlainObject, toPlainObjectOf, toPlainObjectOfTrue, toString, toTrue, toTruthy };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  type _ = undefined;
2
+ /** Returns `U` if `T` is `never` or `any`, otherwise returns `T`. */
3
+ type SetDefaultType<T, U> = [T, U][T extends any ? (0 extends 1 & T ? 1 : 0) : 1];
2
4
  /** Returns `true` if `x` is not `undefined`. */
3
5
  declare const isDefined: <T>(x: T | undefined) => x is T;
4
6
  declare const isTrue: (x: unknown) => x is true;
@@ -7,12 +9,11 @@ declare const toTrue: (x: unknown) => true | _;
7
9
  /** Returns `true` if `x` is `true`, otherwise returns `false`. */
8
10
  declare const asTrue: (x: unknown) => boolean;
9
11
  type Falsy = false | null | undefined | 0 | "";
10
- interface IsFalsy {
11
- (x: unknown): x is Falsy;
12
- <T>(x: T): x is Extract<T, Falsy>;
13
- }
12
+ type ExtractFalsy<T> = SetDefaultType<Extract<T, Falsy>, Falsy>;
14
13
  /** Returns `true` if `Boolean(x)` is `false`. */
15
- declare const isFalsy: IsFalsy;
14
+ declare const isFalsy: <T>(x: T) => x is ExtractFalsy<T>;
15
+ /** Returns `x` if `Boolean(x)` is `false`, otherwise returns `undefined`. */
16
+ declare const toFalsy: <T>(x: T) => ExtractFalsy<T> | _;
16
17
  /** Returns `true` if `Boolean(x)` is `true`. */
17
18
  declare const isTruthy: <T>(x: T) => x is Exclude<T, Falsy>;
18
19
  /** Returns `x` if `Boolean(x)` is `true`, otherwise returns `undefined`. */
@@ -36,53 +37,49 @@ declare const asString: (x: unknown) => string;
36
37
  declare const isNonEmptyString: (x: unknown) => x is string;
37
38
  /** Returns `x` if `x` is a string and not empty, otherwise returns `undefined`. */
38
39
  declare const toNonEmptyString: (x: unknown) => string | _;
39
- type NormalizeArrayType<T> = T extends readonly unknown[] ? T : unknown[];
40
- type ExtractArray<T> = NormalizeArrayType<Extract<T, readonly unknown[]>>;
41
- interface IsArray {
42
- (x: unknown): x is unknown[];
43
- <T>(x: T): x is T extends readonly unknown[] ? T : never;
44
- }
45
- declare const isArray: IsArray;
40
+ type ExtractArray<T> = SetDefaultType<Extract<T, readonly unknown[]>, unknown[]>;
41
+ declare const isArray: <T>(x: T) => x is ExtractArray<T>;
46
42
  /** Returns `x` if `x` is an array. */
47
43
  declare const toArray: <T>(x: T) => ExtractArray<T> | _;
44
+ /** Returns `x` if `x` is an array, otherwise returns `[]` (empty array). */
45
+ declare const asArray: <T>(x: T) => ExtractArray<T>;
48
46
  /** Returns `true` if `x` is an array and has at least one element. */
49
- declare const isNonEmptyArray: IsArray;
47
+ declare const isNonEmptyArray: <T>(x: T) => x is ExtractArray<T>;
50
48
  /** Returns `x` if `x` is an array and has at least one element, otherwise returns `undefined`. */
51
49
  declare const toNonEmptyArray: <T>(x: T) => ExtractArray<T> | _;
52
- /** Returns `x` if `x` is an array, otherwise returns `[]` (empty array). */
53
- declare const asArray: <T>(x: T) => ExtractArray<T>;
50
+ type ExtractObject<T> = SetDefaultType<Extract<T, object>, object>;
51
+ /** Returns `true` if `x` is an object (including array) and not null. */
52
+ declare const isObject: <T>(x: T) => x is ExtractObject<T>;
53
+ /** Returns `x` if `x` is an object (including array). */
54
+ declare const toObject: <T>(x: T) => ExtractObject<T> | _;
55
+ /** Returns `x` if `x` is an object (including array), otherwise returns `{}` (empty object). */
56
+ declare const asObject: <T>(x: T) => ExtractObject<T>;
54
57
  interface PlainObject {
55
58
  [key: PropertyKey]: unknown;
56
59
  }
57
- /** Returns `true` if `x` is an object (including array) and not null. */
58
- declare const isObject: (x: unknown) => x is object;
59
- /** Returns `x` if `x` is an object (including array), otherwise returns `{}` (empty object). */
60
- declare const asObject: (x: unknown) => object;
60
+ type ExtractPlainObject<T> = SetDefaultType<Exclude<Extract<T, object>, readonly unknown[]>, PlainObject>;
61
61
  /** Returns `true` if `x` is a plain object (shallow test), not `null` or array. */
62
- declare const isPlainObject: (x: unknown) => x is PlainObject;
62
+ declare const isPlainObject: <T>(x: T) => x is ExtractPlainObject<T>;
63
63
  /** Returns `x` if `x` is a plain object. */
64
- declare const toPlainObject: (x: unknown) => PlainObject | _;
64
+ declare const toPlainObject: <T>(x: T) => ExtractPlainObject<T> | _;
65
65
  /** Returns `x` if `x` is a plain object, otherwise returns `{}` (empty object). */
66
- declare const asPlainObject: (x: unknown) => PlainObject;
66
+ declare const asPlainObject: <T>(x: T) => ExtractPlainObject<T>;
67
67
  /** Returns `true` if `x` is a plain object and has at least one key. */
68
- declare const isNonEmptyPlainObject: (x: unknown) => x is PlainObject;
68
+ declare const isNonEmptyPlainObject: <T>(x: T) => x is ExtractPlainObject<T>;
69
69
  /** Returns `x` if `x` is a plain object and has at least one key. */
70
- declare const toNonEmptyPlainObject: <T extends PlainObject>(x: T) => T | _;
70
+ declare const toNonEmptyPlainObject: <T>(x: T) => ExtractPlainObject<T> | _;
71
71
  /** Returns `true` if `x` is a plain object and has at least one key with non-undefined value. */
72
- declare const isNonEmptyJSONObject: (x: unknown) => x is PlainObject;
72
+ declare const isNonEmptyJSONObject: <T>(x: T) => x is ExtractPlainObject<T>;
73
73
  /** Returns `x` if `x` is a plain object and has at least one key with non-undefined value, otherwise returns `undefined`. */
74
- declare const toNonEmptyJSONObject: <T extends PlainObject>(x: T) => T | _;
74
+ declare const toNonEmptyJSONObject: <T>(x: T) => ExtractPlainObject<T> | _;
75
+ type ExtractPlainObjectValue<T> = ExtractPlainObject<T>[keyof ExtractPlainObject<T>];
75
76
  /**
76
77
  * Creates an object from `x` with keys `k` if `f(x[k])` returns `true`.
77
78
  * If `x` is not a plain object, or there's no passed props, returns `undefined`.
78
79
  */
79
- declare const toPlainObjectOf: <T>(x: unknown, f: (v: unknown) => v is T) => {
80
- [key: PropertyKey]: T;
81
- } | _;
80
+ declare const toPlainObjectOf: <T, U extends ExtractPlainObjectValue<T>>(x: T, f: (v: ExtractPlainObjectValue<T>) => v is U) => Record<PropertyKey, U> | _;
82
81
  /** Filter props from object `x` whose values are `true`. */
83
- declare const toPlainObjectOfTrue: (x: unknown) => {
84
- [key: PropertyKey]: true;
85
- } | _;
82
+ declare const toPlainObjectOfTrue: (x: unknown) => Record<PropertyKey, true> | _;
86
83
  /**
87
84
  * Returns `x` if `x` is string, otherwise returns `''` (empty string) if
88
85
  * `x` is `null` or `undefined`, otherwise returns `JSON.stringify(x)`.
@@ -97,4 +94,4 @@ declare const returnsFalse: () => false;
97
94
  declare const returnsTrue: () => true;
98
95
  declare const returnsEmptyString: () => string;
99
96
 
100
- export { type ExtractArray, type Falsy, type IsArray, type IsFalsy, type NormalizeArrayType, type PlainObject, type _, asArray, asNumber, asObject, asPlainObject, asString, asTrue, isArray, isBoolean, isDefined, isFalsy, isNonEmptyArray, isNonEmptyJSONObject, isNonEmptyPlainObject, isNonEmptyString, isNumber, isObject, isPlainObject, isString, isTrue, isTruthy, noop, print, returnsEmptyString, returnsFalse, returnsNull, returnsTrue, returnsUndefined, toArray, toBoolean, toNonEmptyArray, toNonEmptyJSONObject, toNonEmptyPlainObject, toNonEmptyString, toNumber, toPlainObject, toPlainObjectOf, toPlainObjectOfTrue, toString, toTrue, toTruthy };
97
+ export { type ExtractArray, type ExtractFalsy, type ExtractObject, type ExtractPlainObject, type Falsy, type PlainObject, type SetDefaultType, type _, asArray, asNumber, asObject, asPlainObject, asString, asTrue, isArray, isBoolean, isDefined, isFalsy, isNonEmptyArray, isNonEmptyJSONObject, isNonEmptyPlainObject, isNonEmptyString, isNumber, isObject, isPlainObject, isString, isTrue, isTruthy, noop, print, returnsEmptyString, returnsFalse, returnsNull, returnsTrue, returnsUndefined, toArray, toBoolean, toFalsy, toNonEmptyArray, toNonEmptyJSONObject, toNonEmptyPlainObject, toNonEmptyString, toNumber, toObject, toPlainObject, toPlainObjectOf, toPlainObjectOfTrue, toString, toTrue, toTruthy };
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ var isTrue = (x) => x === true;
7
7
  var toTrue = (x) => x === true ? true : _;
8
8
  var asTrue = (x) => x === true ? x : false;
9
9
  var isFalsy = (x) => !x;
10
+ var toFalsy = (x) => isFalsy(x) ? x : _;
10
11
  var isTruthy = (x) => !!x;
11
12
  var toTruthy = (x) => isTruthy(x) ? x : _;
12
13
  var isBoolean = (x) => x === true || x === false;
@@ -21,10 +22,11 @@ var isNonEmptyString = (x) => isString(x) && x !== "";
21
22
  var toNonEmptyString = (x) => isNonEmptyString(x) ? x : _;
22
23
  var isArray = Array.isArray;
23
24
  var toArray = (x) => isArray(x) ? x : _;
25
+ var asArray = (x) => isArray(x) ? x : [];
24
26
  var isNonEmptyArray = (x) => isArray(x) && x.length > 0;
25
27
  var toNonEmptyArray = (x) => isNonEmptyArray(x) ? x : _;
26
- var asArray = (x) => isArray(x) ? x : [];
27
28
  var isObject = (x) => x !== null && typeof x === "object";
29
+ var toObject = (x) => isObject(x) ? x : _;
28
30
  var asObject = (x) => isObject(x) ? x : {};
29
31
  var isPlainObject = (x) => isObject(x) && !isArray(x);
30
32
  var toPlainObject = (x) => isPlainObject(x) ? x : _;
@@ -98,11 +100,13 @@ exports.returnsTrue = returnsTrue;
98
100
  exports.returnsUndefined = returnsUndefined;
99
101
  exports.toArray = toArray;
100
102
  exports.toBoolean = toBoolean;
103
+ exports.toFalsy = toFalsy;
101
104
  exports.toNonEmptyArray = toNonEmptyArray;
102
105
  exports.toNonEmptyJSONObject = toNonEmptyJSONObject;
103
106
  exports.toNonEmptyPlainObject = toNonEmptyPlainObject;
104
107
  exports.toNonEmptyString = toNonEmptyString;
105
108
  exports.toNumber = toNumber;
109
+ exports.toObject = toObject;
106
110
  exports.toPlainObject = toPlainObject;
107
111
  exports.toPlainObjectOf = toPlainObjectOf;
108
112
  exports.toPlainObjectOfTrue = toPlainObjectOfTrue;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/is-to-as.ts","../src/returns.ts"],"names":[],"mappings":"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","file":"index.js"}
1
+ {"version":3,"sources":["../src/is-to-as.ts","../src/returns.ts"],"names":[],"mappings":"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","file":"index.js"}
package/dist/index.mjs CHANGED
@@ -5,6 +5,7 @@ var isTrue = (x) => x === true;
5
5
  var toTrue = (x) => x === true ? true : _;
6
6
  var asTrue = (x) => x === true ? x : false;
7
7
  var isFalsy = (x) => !x;
8
+ var toFalsy = (x) => isFalsy(x) ? x : _;
8
9
  var isTruthy = (x) => !!x;
9
10
  var toTruthy = (x) => isTruthy(x) ? x : _;
10
11
  var isBoolean = (x) => x === true || x === false;
@@ -19,10 +20,11 @@ var isNonEmptyString = (x) => isString(x) && x !== "";
19
20
  var toNonEmptyString = (x) => isNonEmptyString(x) ? x : _;
20
21
  var isArray = Array.isArray;
21
22
  var toArray = (x) => isArray(x) ? x : _;
23
+ var asArray = (x) => isArray(x) ? x : [];
22
24
  var isNonEmptyArray = (x) => isArray(x) && x.length > 0;
23
25
  var toNonEmptyArray = (x) => isNonEmptyArray(x) ? x : _;
24
- var asArray = (x) => isArray(x) ? x : [];
25
26
  var isObject = (x) => x !== null && typeof x === "object";
27
+ var toObject = (x) => isObject(x) ? x : _;
26
28
  var asObject = (x) => isObject(x) ? x : {};
27
29
  var isPlainObject = (x) => isObject(x) && !isArray(x);
28
30
  var toPlainObject = (x) => isPlainObject(x) ? x : _;
@@ -67,6 +69,6 @@ var returnsFalse = () => false;
67
69
  var returnsTrue = () => true;
68
70
  var returnsEmptyString = () => "";
69
71
 
70
- export { asArray, asNumber, asObject, asPlainObject, asString, asTrue, isArray, isBoolean, isDefined, isFalsy, isNonEmptyArray, isNonEmptyJSONObject, isNonEmptyPlainObject, isNonEmptyString, isNumber, isObject, isPlainObject, isString, isTrue, isTruthy, noop, print, returnsEmptyString, returnsFalse, returnsNull, returnsTrue, returnsUndefined, toArray, toBoolean, toNonEmptyArray, toNonEmptyJSONObject, toNonEmptyPlainObject, toNonEmptyString, toNumber, toPlainObject, toPlainObjectOf, toPlainObjectOfTrue, toString, toTrue, toTruthy };
72
+ export { asArray, asNumber, asObject, asPlainObject, asString, asTrue, isArray, isBoolean, isDefined, isFalsy, isNonEmptyArray, isNonEmptyJSONObject, isNonEmptyPlainObject, isNonEmptyString, isNumber, isObject, isPlainObject, isString, isTrue, isTruthy, noop, print, returnsEmptyString, returnsFalse, returnsNull, returnsTrue, returnsUndefined, toArray, toBoolean, toFalsy, toNonEmptyArray, toNonEmptyJSONObject, toNonEmptyPlainObject, toNonEmptyString, toNumber, toObject, toPlainObject, toPlainObjectOf, toPlainObjectOfTrue, toString, toTrue, toTruthy };
71
73
  //# sourceMappingURL=index.mjs.map
72
74
  //# sourceMappingURL=index.mjs.map
@@ -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,7 +1,7 @@
1
1
  {
2
2
  "name": "@wopjs/cast",
3
- "version": "0.1.7",
4
- "description": "Filter types from unknown",
3
+ "version": "0.1.9",
4
+ "description": "Type-safe utilities for filtering and coercing unknown values in TypeScript.",
5
5
  "repository": "wopjs/cast",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
@@ -25,7 +25,14 @@
25
25
  },
26
26
  "keywords": [
27
27
  "typescript",
28
- "coerce"
28
+ "type-guard",
29
+ "type-narrowing",
30
+ "type-safe",
31
+ "coerce",
32
+ "cast",
33
+ "unknown",
34
+ "validation",
35
+ "filter"
29
36
  ],
30
37
  "maintainers": [
31
38
  {
@@ -1,3 +1,5 @@
1
+ import type { PlainObject } from ".";
2
+
1
3
  import { describe, it, expect } from "vitest";
2
4
 
3
5
  import {
@@ -7,6 +9,7 @@ import {
7
9
  asTrue,
8
10
  isTruthy,
9
11
  isFalsy,
12
+ toFalsy,
10
13
  isBoolean,
11
14
  toBoolean,
12
15
  isNumber,
@@ -24,6 +27,7 @@ import {
24
27
  asArray,
25
28
  toNonEmptyArray,
26
29
  isObject,
30
+ toObject,
27
31
  asObject,
28
32
  isPlainObject,
29
33
  toPlainObject,
@@ -67,6 +71,33 @@ describe("primitive.ts", () => {
67
71
  expect(isTruthy(true)).toBe(true);
68
72
  expect(isTruthy(false)).toBe(false);
69
73
  expect(isTruthy(1)).toBe(true);
74
+
75
+ {
76
+ // Type narrowing - excludes falsy from union
77
+ const val = castType<string | null | undefined>("hello");
78
+ if (isTruthy(val)) {
79
+ const check: string = val;
80
+ expect(check).toBe("hello");
81
+ }
82
+ }
83
+
84
+ {
85
+ // Type narrowing - excludes all falsy types
86
+ const val = castType<number | false | null | undefined | "" | 0>(42);
87
+ if (isTruthy(val)) {
88
+ const check: number = val;
89
+ expect(check).toBe(42);
90
+ }
91
+ }
92
+
93
+ {
94
+ // Type narrowing - narrows boolean to true
95
+ const val = castType<boolean>(true);
96
+ if (isTruthy(val)) {
97
+ const check: true = val;
98
+ expect(check).toBe(true);
99
+ }
100
+ }
70
101
  });
71
102
 
72
103
  it("toTruthy", () => {
@@ -89,6 +120,71 @@ describe("primitive.ts", () => {
89
120
  expect(isFalsy(true)).toBe(false);
90
121
  expect(isFalsy(false)).toBe(true);
91
122
  expect(isFalsy(1)).toBe(false);
123
+
124
+ {
125
+ // Type narrowing - extracts falsy from union
126
+ const val = castType<string | null | undefined>(null);
127
+ if (isFalsy(val)) {
128
+ const check: null | undefined = val;
129
+ expect(check).toBe(null);
130
+ }
131
+ }
132
+
133
+ {
134
+ // Type narrowing - extracts all falsy types
135
+ const val = castType<number | false | null | undefined | "" | 0>(0);
136
+ if (isFalsy(val)) {
137
+ const check: false | null | undefined | "" | 0 = val;
138
+ expect(check).toBe(0);
139
+ }
140
+ }
141
+
142
+ {
143
+ // Type narrowing - narrows boolean to false
144
+ const val = castType<boolean>(false);
145
+ if (isFalsy(val)) {
146
+ const check: false = val;
147
+ expect(check).toBe(false);
148
+ }
149
+ }
150
+ });
151
+
152
+ it("toFalsy", () => {
153
+ expect(toFalsy(false)).toBe(false);
154
+ expect(toFalsy(null)).toBe(null);
155
+ expect(toFalsy(undefined)).toBe(undefined);
156
+ expect(toFalsy(0)).toBe(0);
157
+ expect(toFalsy("")).toBe("");
158
+ expect(toFalsy(true)).toBe(undefined);
159
+ expect(toFalsy(1)).toBe(undefined);
160
+ expect(toFalsy("hello")).toBe(undefined);
161
+
162
+ {
163
+ // Type narrowing - extracts falsy from union
164
+ const val = castType<string | null | undefined>(null);
165
+ const result = toFalsy(val);
166
+ if (result !== undefined) {
167
+ const check: "" | null = result;
168
+ expect(check).toBe(null);
169
+ }
170
+ }
171
+
172
+ {
173
+ // Type narrowing - returns undefined for truthy value
174
+ const val = castType<string | null>("hello");
175
+ const result: "" | null | undefined = toFalsy(val);
176
+ expect(result).toBe(undefined);
177
+ }
178
+
179
+ {
180
+ // Type narrowing - extracts falsy from number union
181
+ const val = castType<number | false>(0);
182
+ const result = toFalsy(val);
183
+ if (result !== undefined) {
184
+ const check: 0 | false = result;
185
+ expect(check).toBe(0);
186
+ }
187
+ }
92
188
  });
93
189
 
94
190
  it("isBoolean", () => {
@@ -208,6 +304,16 @@ describe("primitive.ts", () => {
208
304
  expect(check).toBe(undefined);
209
305
  }
210
306
  }
307
+
308
+ {
309
+ // Type narrowing - generic
310
+ const _fn = <T>(x: T): void => {
311
+ if (isArray(x)) {
312
+ const y: readonly any[] = x;
313
+ expect(Array.isArray(y)).toBe(true);
314
+ }
315
+ };
316
+ }
211
317
  });
212
318
 
213
319
  it("toArray", () => {
@@ -276,6 +382,15 @@ describe("primitive.ts", () => {
276
382
  const arr = castType<string>("hello");
277
383
  const result: unknown[] | undefined = toArray(arr);
278
384
  expect(result).toBe(undefined);
385
+ toArray(arr)?.map(x => x);
386
+ }
387
+
388
+ {
389
+ // Type narrowing - any returns any[]
390
+ const arr = castType<any>("hello");
391
+ const result: unknown[] | undefined = toArray(arr);
392
+ expect(result).toBe(undefined);
393
+ toArray(arr)?.map(x => x);
279
394
  }
280
395
  });
281
396
 
@@ -411,6 +526,7 @@ describe("primitive.ts", () => {
411
526
  const arr = castType<unknown>(["a", "b"]);
412
527
  const result: unknown[] = asArray(arr);
413
528
  expect(result).toEqual(["a", "b"]);
529
+ asArray(arr).map(x => x);
414
530
  }
415
531
 
416
532
  {
@@ -418,6 +534,7 @@ describe("primitive.ts", () => {
418
534
  const arr = castType<string>("hello");
419
535
  const result: unknown[] = asArray(arr);
420
536
  expect(result).toEqual([]);
537
+ asArray(arr).map(x => x);
421
538
  }
422
539
  });
423
540
 
@@ -466,17 +583,28 @@ describe("primitive.ts", () => {
466
583
  }
467
584
 
468
585
  {
469
- // Type narrowing - unknown input returns unknown[] | undefined
586
+ // Type narrowing - unknown input returns unknown[]
470
587
  const arr = castType<unknown>(["a", "b"]);
471
- const result: unknown[] | undefined = toNonEmptyArray(arr);
472
- expect(result).toEqual(["a", "b"]);
588
+ let result = toNonEmptyArray(arr);
589
+ if (result) {
590
+ // rule out never
591
+ let check = result;
592
+ check = castType<unknown[]>(result);
593
+ expect(check).toEqual(["a", "b"]);
594
+ }
473
595
  }
474
596
 
475
597
  {
476
598
  // Type narrowing - non-array type (string) returns unknown[] | undefined
477
599
  const arr = castType<string>("hello");
478
- const result: unknown[] | undefined = toNonEmptyArray(arr);
600
+ const result = toNonEmptyArray(arr);
479
601
  expect(result).toBe(undefined);
602
+ if (result) {
603
+ // rule out never
604
+ let _check = result;
605
+ _check = castType<unknown[]>(result);
606
+ throw new Error("Unreachable");
607
+ }
480
608
  }
481
609
  });
482
610
 
@@ -484,59 +612,410 @@ describe("primitive.ts", () => {
484
612
  expect(isObject({})).toBe(true);
485
613
  expect(isObject([])).toBe(true);
486
614
  expect(isObject(null)).toBe(false);
615
+
616
+ {
617
+ // Type narrowing - preserves object type
618
+ const obj = castType<{ a: string }>({ a: "hello" });
619
+ if (isObject(obj)) {
620
+ const check: { a: string } = obj;
621
+ expect(check).toBe(obj);
622
+ }
623
+ }
624
+
625
+ {
626
+ // Type narrowing - extracts object from union
627
+ const obj = castType<string | { a: string }>({ a: "hello" });
628
+ if (isObject(obj)) {
629
+ const check: object = obj;
630
+ expect(check).toEqual({ a: "hello" });
631
+ }
632
+ }
633
+
634
+ {
635
+ // Type narrowing - arrays are objects
636
+ const arr = castType<string[]>(["a", "b"]);
637
+ if (isObject(arr)) {
638
+ const check: string[] = arr;
639
+ expect(check).toBe(arr);
640
+ }
641
+ }
642
+
643
+ {
644
+ // Type narrowing - unknown input narrows to object
645
+ const obj = castType<unknown>({ a: 1 });
646
+ if (isObject(obj)) {
647
+ const check: object = obj;
648
+ expect(check).toEqual({ a: 1 });
649
+ }
650
+ }
651
+
652
+ {
653
+ // Type narrowing - null | object union extracts object
654
+ const obj = castType<null | { x: number }>({ x: 42 });
655
+ if (isObject(obj)) {
656
+ const check: { x: number } = obj;
657
+ expect(check).toEqual({ x: 42 });
658
+ }
659
+ }
660
+ });
661
+
662
+ it("toObject", () => {
663
+ expect(toObject({})).toEqual({});
664
+ expect(toObject([])).toEqual([]);
665
+ expect(toObject(null)).toBe(undefined);
666
+
667
+ {
668
+ // Type narrowing - preserves object type
669
+ const obj = castType<{ a: string }>({ a: "hello" });
670
+ const result = toObject(obj);
671
+ if (result) {
672
+ const check: { a: string } = result;
673
+ expect(check).toBe(obj);
674
+ }
675
+ }
676
+
677
+ {
678
+ // Type narrowing - extracts object from union
679
+ const obj = castType<string | { a: string }>({ a: "hello" });
680
+ const result = toObject(obj);
681
+ if (result) {
682
+ const check: { a: string } = result;
683
+ expect(check).toEqual({ a: "hello" });
684
+ }
685
+ }
686
+
687
+ {
688
+ // Type narrowing - preserves array (arrays are objects)
689
+ const arr = castType<string[]>(["a", "b"]);
690
+ const result = toObject(arr);
691
+ if (result) {
692
+ const check: string[] = result;
693
+ expect(check).toBe(arr);
694
+ }
695
+ }
696
+
697
+ {
698
+ // Type narrowing - unknown input returns object | undefined
699
+ const obj = castType<unknown>({ a: 1 });
700
+ const result: object | undefined = toObject(obj);
701
+ expect(result).toEqual({ a: 1 });
702
+ }
703
+
704
+ {
705
+ // Type narrowing - non-object type (string) returns undefined
706
+ const obj = castType<string>("hello");
707
+ const result: object | undefined = toObject(obj);
708
+ expect(result).toBe(undefined);
709
+ }
710
+
711
+ {
712
+ // Type narrowing - null | object union extracts object
713
+ const obj = castType<null | { x: number }>({ x: 42 });
714
+ const result = toObject(obj);
715
+ if (result) {
716
+ const check: { x: number } = result;
717
+ expect(check).toEqual({ x: 42 });
718
+ }
719
+ }
487
720
  });
488
721
 
489
722
  it("asObject", () => {
490
723
  expect(asObject({})).toEqual({});
491
724
  expect(asObject([])).toEqual([]);
492
725
  expect(asObject(null)).toEqual({});
726
+
727
+ {
728
+ // Type narrowing - preserves object type
729
+ const obj = castType<{ a: string }>({ a: "hello" });
730
+ const result: { a: string } = asObject(obj);
731
+ expect(result).toBe(obj);
732
+ }
733
+
734
+ {
735
+ // Type narrowing - extracts object from union
736
+ const obj = castType<string | { a: string }>({ a: "hello" });
737
+ const result: { a: string } = asObject(obj);
738
+ expect(result).toEqual({ a: "hello" });
739
+ }
740
+
741
+ {
742
+ // Type narrowing - preserves array (arrays are objects)
743
+ const arr = castType<string[]>(["a", "b"]);
744
+ const result: string[] = asObject(arr);
745
+ expect(result).toBe(arr);
746
+ }
747
+
748
+ {
749
+ // Type narrowing - unknown input returns object
750
+ const obj = castType<unknown>({ a: 1 });
751
+ const result: object = asObject(obj);
752
+ expect(result).toEqual({ a: 1 });
753
+ }
754
+
755
+ {
756
+ // Type narrowing - non-object type (string) returns object
757
+ const obj = castType<string>("hello");
758
+ const result: object = asObject(obj);
759
+ expect(result).toEqual({});
760
+ }
761
+
762
+ {
763
+ // Type narrowing - null | object union extracts object
764
+ const obj = castType<null | { x: number }>({ x: 42 });
765
+ const result: { x: number } = asObject(obj);
766
+ expect(result).toEqual({ x: 42 });
767
+ }
493
768
  });
494
769
 
495
770
  it("isPlainObject", () => {
496
771
  expect(isPlainObject({})).toBe(true);
497
772
  expect(isPlainObject([])).toBe(false);
498
773
  expect(isPlainObject(null)).toBe(false);
774
+
775
+ {
776
+ // Type narrowing - unknown input narrows to PlainObject
777
+ const obj = castType<unknown>({ a: 1 });
778
+ if (isPlainObject(obj)) {
779
+ const check: PlainObject = obj;
780
+ expect(check).toEqual({ a: 1 });
781
+ }
782
+ }
783
+
784
+ {
785
+ // Type narrowing - excludes array from union
786
+ const obj = castType<{ a: number } | number[]>({ a: 1 });
787
+ if (isPlainObject(obj)) {
788
+ const check: PlainObject = obj;
789
+ expect(check).toEqual({ a: 1 });
790
+ }
791
+ }
792
+
793
+ {
794
+ // Type narrowing - null | object union extracts PlainObject
795
+ const obj = castType<null | { x: number }>({ x: 42 });
796
+ if (isPlainObject(obj)) {
797
+ const check: { x: number } = obj;
798
+ expect(check).toEqual({ x: 42 });
799
+ }
800
+ }
499
801
  });
500
802
 
501
803
  it("toPlainObject", () => {
502
804
  expect(toPlainObject({})).toEqual({});
503
805
  expect(toPlainObject([])).toBe(undefined);
504
806
  expect(toPlainObject(null)).toBe(undefined);
807
+
808
+ {
809
+ // Type narrowing - unknown input returns PlainObject | undefined
810
+ const obj = castType<unknown>({ a: 1 });
811
+ const result: PlainObject | undefined = toPlainObject(obj);
812
+ expect(result).toEqual({ a: 1 });
813
+ }
814
+
815
+ {
816
+ // Type narrowing - array returns undefined
817
+ const arr = castType<number[]>([1, 2]);
818
+ const result: PlainObject | undefined = toPlainObject(arr);
819
+ expect(result).toBe(undefined);
820
+ }
505
821
  });
506
822
 
507
823
  it("asPlainObject", () => {
508
824
  expect(asPlainObject({})).toEqual({});
509
825
  expect(asPlainObject([])).toEqual({});
510
826
  expect(asPlainObject(null)).toEqual({});
827
+
828
+ {
829
+ // Type narrowing - unknown input returns PlainObject
830
+ const obj = castType<unknown>({ a: 1 });
831
+ const result: PlainObject = asPlainObject(obj);
832
+ expect(result).toEqual({ a: 1 });
833
+ }
834
+
835
+ {
836
+ // Type narrowing - array returns empty object
837
+ const arr = castType<number[]>([1, 2]);
838
+ const result: PlainObject = asPlainObject(arr);
839
+ expect(result).toEqual({});
840
+ }
841
+
842
+ {
843
+ // Type narrowing - non-object returns empty object
844
+ const val = castType<string>("hello");
845
+ const result: PlainObject = asPlainObject(val);
846
+ expect(result).toEqual({});
847
+ }
511
848
  });
512
849
 
513
850
  it("isNonEmptyPlainObject", () => {
514
851
  expect(isNonEmptyPlainObject({ a: 1 })).toBe(true);
515
852
  expect(isNonEmptyPlainObject({})).toBe(false);
516
853
  expect(isNonEmptyPlainObject([])).toBe(false);
854
+
855
+ {
856
+ // Type narrowing - unknown input narrows to PlainObject
857
+ const obj = castType<unknown>({ a: 1 });
858
+ if (isNonEmptyPlainObject(obj)) {
859
+ const check: PlainObject = obj;
860
+ expect(check).toEqual({ a: 1 });
861
+ }
862
+ }
863
+
864
+ {
865
+ // Type narrowing - empty object returns false
866
+ const obj = castType<{ a?: number }>({});
867
+ if (isNonEmptyPlainObject(obj)) {
868
+ const check: PlainObject = obj;
869
+ expect(check).toEqual({});
870
+ } else {
871
+ expect(obj).toEqual({});
872
+ }
873
+ }
874
+
875
+ {
876
+ // Type narrowing - excludes array
877
+ const obj = castType<{ a: number } | number[]>({ a: 1 });
878
+ if (isNonEmptyPlainObject(obj)) {
879
+ const check: PlainObject = obj;
880
+ expect(check).toEqual({ a: 1 });
881
+ }
882
+ }
517
883
  });
518
884
 
519
885
  it("toNonEmptyPlainObject", () => {
520
886
  expect(toNonEmptyPlainObject({ a: 1 })).toEqual({ a: 1 });
521
887
  expect(toNonEmptyPlainObject({})).toBe(undefined);
888
+
889
+ {
890
+ // Type narrowing - preserves object type
891
+ const obj = castType<{ a: number }>({ a: 1 });
892
+ const result = toNonEmptyPlainObject(obj);
893
+ if (result) {
894
+ const check: { a: number } = result;
895
+ expect(check).toEqual({ a: 1 });
896
+ }
897
+ }
898
+
899
+ {
900
+ // Type narrowing - undefined input returns undefined
901
+ const obj = castType<{ a: number } | undefined>(undefined);
902
+ const result: { a: number } | undefined = toNonEmptyPlainObject(obj);
903
+ expect(result).toBe(undefined);
904
+ }
905
+
906
+ {
907
+ // Type narrowing - empty object returns undefined
908
+ const obj = castType<{ a?: number }>({});
909
+ const result = toNonEmptyPlainObject(obj);
910
+ expect(result).toBe(undefined);
911
+ }
912
+
913
+ {
914
+ // type narrowing - non-object type returns PlainObject | undefined
915
+ const obj = castType<number>(42);
916
+ const result: PlainObject | undefined = toNonEmptyPlainObject(obj);
917
+ expect(result).toBe(undefined);
918
+ }
522
919
  });
523
920
 
524
921
  it("isNonEmptyJSONObject", () => {
525
922
  expect(isNonEmptyJSONObject({ a: 1 })).toBe(true);
526
923
  expect(isNonEmptyJSONObject({})).toBe(false);
527
924
  expect(isNonEmptyJSONObject([])).toBe(false);
925
+ expect(isNonEmptyJSONObject({ a: undefined })).toBe(false);
926
+
927
+ {
928
+ // Type narrowing - unknown input narrows to PlainObject
929
+ const obj = castType<unknown>({ a: 1 });
930
+ if (isNonEmptyJSONObject(obj)) {
931
+ const check: PlainObject = obj;
932
+ expect(check).toEqual({ a: 1 });
933
+ }
934
+ }
935
+
936
+ {
937
+ // Type narrowing - object with only undefined values returns false
938
+ const obj = castType<{ a?: number }>({ a: undefined });
939
+ if (isNonEmptyJSONObject(obj)) {
940
+ const check: PlainObject = obj;
941
+ expect(check).toEqual({});
942
+ } else {
943
+ expect(obj).toEqual({ a: undefined });
944
+ }
945
+ }
946
+
947
+ {
948
+ // Type narrowing - excludes array
949
+ const obj = castType<{ a: number } | number[]>({ a: 1 });
950
+ if (isNonEmptyJSONObject(obj)) {
951
+ const check: PlainObject = obj;
952
+ expect(check).toEqual({ a: 1 });
953
+ }
954
+ }
528
955
  });
529
956
 
530
957
  it("toNonEmptyJSONObject", () => {
531
958
  expect(toNonEmptyJSONObject({ a: 1 })).toEqual({ a: 1 });
532
959
  expect(toNonEmptyJSONObject({})).toBe(undefined);
960
+
961
+ {
962
+ // Type narrowing - preserves object type
963
+ const obj = castType<{ a: number }>({ a: 1 });
964
+ const result = toNonEmptyJSONObject(obj);
965
+ if (result) {
966
+ const check: { a: number } = result;
967
+ expect(check).toEqual({ a: 1 });
968
+ }
969
+ }
970
+
971
+ {
972
+ // Type narrowing - undefined input returns undefined
973
+ const obj = castType<{ a: number } | undefined>(undefined);
974
+ const result: { a: number } | undefined = toNonEmptyJSONObject(obj);
975
+ expect(result).toBe(undefined);
976
+ }
977
+
978
+ {
979
+ // Type narrowing - object with only undefined values returns undefined
980
+ const obj = castType<{ a: number; b?: string }>({ a: undefined as unknown as number });
981
+ const result = toNonEmptyJSONObject(obj);
982
+ expect(result).toBe(undefined);
983
+ }
533
984
  });
534
985
 
535
986
  it("toPlainObjectOf", () => {
536
987
  expect(toPlainObjectOf({ a: true, b: false }, isTrue)).toEqual({ a: true });
988
+ // @ts-expect-error type mismatched
537
989
  expect(toPlainObjectOf({ a: 1, b: 2 }, isTrue)).toBe(undefined);
538
990
  expect(toPlainObjectOf({ a: 1, b: 2 }, isTruthy)).toEqual({ a: 1, b: 2 });
539
991
  expect(toPlainObjectOf(undefined, isTrue)).toBe(undefined);
992
+
993
+ {
994
+ // Type narrowing - result type matches predicate
995
+ const obj = castType<{ a: unknown; b: unknown }>({ a: "hello", b: 123 });
996
+ const result = toPlainObjectOf(obj, isString);
997
+ if (result) {
998
+ const check: { [key: PropertyKey]: string } = result;
999
+ expect(check).toEqual({ a: "hello" });
1000
+ }
1001
+ }
1002
+
1003
+ {
1004
+ // Type narrowing - filters to number type
1005
+ const obj = castType<{ a: unknown; b: unknown }>({ a: 1, b: "hello" });
1006
+ const result = toPlainObjectOf(obj, isNumber);
1007
+ if (result) {
1008
+ const check: { [key: PropertyKey]: number } = result;
1009
+ expect(check).toEqual({ a: 1 });
1010
+ }
1011
+ }
1012
+
1013
+ {
1014
+ // Type narrowing - returns undefined when no values match
1015
+ const obj = castType<{ a: unknown; b: unknown }>({ a: "hello", b: "world" });
1016
+ const result = toPlainObjectOf(obj, isNumber);
1017
+ expect(result).toBe(undefined);
1018
+ }
540
1019
  });
541
1020
 
542
1021
  it("toPlainObjectOfTrue", () => {
package/src/is-to-as.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  const _ = undefined;
2
2
  export type _ = undefined;
3
3
 
4
+ /** Returns `U` if `T` is `never` or `any`, otherwise returns `T`. */
5
+ export type SetDefaultType<T, U> = [T, U][T extends any ? (0 extends 1 & T ? 1 : 0) : 1];
6
+
4
7
  /** Returns `true` if `x` is not `undefined`. */
5
8
  export const isDefined = <T>(x: T | undefined): x is T => x !== _;
6
9
 
@@ -14,13 +17,13 @@ export const asTrue = (x: unknown): boolean => (x === true ? x : false);
14
17
 
15
18
  export type Falsy = false | null | undefined | 0 | "";
16
19
 
17
- export interface IsFalsy {
18
- (x: unknown): x is Falsy;
19
- <T>(x: T): x is Extract<T, Falsy>;
20
- }
20
+ export type ExtractFalsy<T> = SetDefaultType<Extract<T, Falsy>, Falsy>;
21
21
 
22
22
  /** Returns `true` if `Boolean(x)` is `false`. */
23
- export const isFalsy: IsFalsy = (x: unknown): x is Falsy => !x;
23
+ export const isFalsy = <T>(x: T): x is ExtractFalsy<T> => !x;
24
+
25
+ /** Returns `x` if `Boolean(x)` is `false`, otherwise returns `undefined`. */
26
+ export const toFalsy = <T>(x: T): ExtractFalsy<T> | _ => (isFalsy(x) ? x : _);
24
27
 
25
28
  /** Returns `true` if `Boolean(x)` is `true`. */
26
29
  export const isTruthy = <T>(x: T): x is Exclude<T, Falsy> => !!x;
@@ -57,74 +60,80 @@ export const isNonEmptyString = (x: unknown): x is string => isString(x) && x !=
57
60
  /** Returns `x` if `x` is a string and not empty, otherwise returns `undefined`. */
58
61
  export const toNonEmptyString = (x: unknown): string | _ => (isNonEmptyString(x) ? x : _);
59
62
 
60
- export type NormalizeArrayType<T> = T extends readonly unknown[] ? T : unknown[];
63
+ export type ExtractArray<T> = SetDefaultType<Extract<T, readonly unknown[]>, unknown[]>;
61
64
 
62
- export type ExtractArray<T> = NormalizeArrayType<Extract<T, readonly unknown[]>>;
63
-
64
- export interface IsArray {
65
- (x: unknown): x is unknown[];
66
- <T>(x: T): x is T extends readonly unknown[] ? T : never;
67
- }
68
-
69
- export const isArray: IsArray = Array.isArray;
65
+ export const isArray = Array.isArray as <T>(x: T) => x is ExtractArray<T>;
70
66
 
71
67
  /** Returns `x` if `x` is an array. */
72
- export const toArray = <T>(x: T): ExtractArray<T> | _ => (isArray(x) ? (x as ExtractArray<T>) : _);
68
+ export const toArray = <T>(x: T): ExtractArray<T> | _ => (isArray(x) ? x : _);
69
+
70
+ /** Returns `x` if `x` is an array, otherwise returns `[]` (empty array). */
71
+ export const asArray = <T>(x: T): ExtractArray<T> => (isArray(x) ? x : ([] as ExtractArray<T>));
73
72
 
74
73
  /** Returns `true` if `x` is an array and has at least one element. */
75
- export const isNonEmptyArray: IsArray = (x: unknown): x is unknown[] => isArray(x) && x.length > 0;
74
+ export const isNonEmptyArray = <T>(x: T): x is ExtractArray<T> => isArray(x) && x.length > 0;
76
75
 
77
76
  /** Returns `x` if `x` is an array and has at least one element, otherwise returns `undefined`. */
78
- export const toNonEmptyArray = <T>(x: T): ExtractArray<T> | _ => (isNonEmptyArray(x) ? (x as ExtractArray<T>) : _);
77
+ export const toNonEmptyArray = <T>(x: T): ExtractArray<T> | _ => (isNonEmptyArray(x) ? x : _);
79
78
 
80
- /** Returns `x` if `x` is an array, otherwise returns `[]` (empty array). */
81
- export const asArray = <T>(x: T): ExtractArray<T> => (isArray(x) ? (x as ExtractArray<T>) : ([] as ExtractArray<T>));
79
+ export type ExtractObject<T> = SetDefaultType<Extract<T, object>, object>;
80
+
81
+ /** Returns `true` if `x` is an object (including array) and not null. */
82
+ export const isObject = <T>(x: T): x is ExtractObject<T> => x !== null && typeof x === "object";
83
+
84
+ /** Returns `x` if `x` is an object (including array). */
85
+ export const toObject = <T>(x: T): ExtractObject<T> | _ => (isObject(x) ? x : _);
86
+
87
+ /** Returns `x` if `x` is an object (including array), otherwise returns `{}` (empty object). */
88
+ export const asObject = <T>(x: T): ExtractObject<T> => (isObject(x) ? x : ({} as ExtractObject<T>));
82
89
 
83
90
  export interface PlainObject {
84
91
  [key: PropertyKey]: unknown;
85
92
  }
86
93
 
87
- /** Returns `true` if `x` is an object (including array) and not null. */
88
- export const isObject = (x: unknown): x is object => x !== null && typeof x === "object";
89
-
90
- /** Returns `x` if `x` is an object (including array), otherwise returns `{}` (empty object). */
91
- export const asObject = (x: unknown): object => (isObject(x) ? x : {});
94
+ export type ExtractPlainObject<T> = SetDefaultType<Exclude<Extract<T, object>, readonly unknown[]>, PlainObject>;
92
95
 
93
96
  /** Returns `true` if `x` is a plain object (shallow test), not `null` or array. */
94
- export const isPlainObject = (x: unknown): x is PlainObject => isObject(x) && !isArray(x);
97
+ export const isPlainObject = <T>(x: T): x is ExtractPlainObject<T> => isObject(x) && !isArray(x);
95
98
 
96
99
  /** Returns `x` if `x` is a plain object. */
97
- export const toPlainObject = (x: unknown): PlainObject | _ => (isPlainObject(x) ? x : _);
100
+ export const toPlainObject = <T>(x: T): ExtractPlainObject<T> | _ => (isPlainObject(x) ? x : _);
98
101
 
99
102
  /** Returns `x` if `x` is a plain object, otherwise returns `{}` (empty object). */
100
- export const asPlainObject = (x: unknown): PlainObject => (isPlainObject(x) ? x : {});
103
+ export const asPlainObject = <T>(x: T): ExtractPlainObject<T> => (isPlainObject(x) ? x : ({} as ExtractPlainObject<T>));
101
104
 
102
105
  /** Returns `true` if `x` is a plain object and has at least one key. */
103
- export const isNonEmptyPlainObject = (x: unknown): x is PlainObject => isPlainObject(x) && Object.keys(x).length > 0;
106
+ export const isNonEmptyPlainObject = <T>(x: T): x is ExtractPlainObject<T> =>
107
+ isPlainObject(x) && Object.keys(x).length > 0;
104
108
 
105
109
  /** Returns `x` if `x` is a plain object and has at least one key. */
106
- export const toNonEmptyPlainObject = <T extends PlainObject>(x: T): T | _ => (isNonEmptyPlainObject(x) ? x : _);
110
+ export const toNonEmptyPlainObject = <T>(x: T): ExtractPlainObject<T> | _ => (isNonEmptyPlainObject(x) ? x : _);
107
111
 
108
112
  /** Returns `true` if `x` is a plain object and has at least one key with non-undefined value. */
109
- export const isNonEmptyJSONObject = (x: unknown): x is PlainObject =>
113
+ export const isNonEmptyJSONObject = <T>(x: T): x is ExtractPlainObject<T> =>
110
114
  isPlainObject(x) && Object.values(x).some(isDefined);
111
115
 
112
116
  /** Returns `x` if `x` is a plain object and has at least one key with non-undefined value, otherwise returns `undefined`. */
113
- export const toNonEmptyJSONObject = <T extends PlainObject>(x: T): T | _ => (isNonEmptyJSONObject(x) ? x : _);
117
+ export const toNonEmptyJSONObject = <T>(x: T): ExtractPlainObject<T> | _ => (isNonEmptyJSONObject(x) ? x : _);
118
+
119
+ type ExtractPlainObjectValue<T> = ExtractPlainObject<T>[keyof ExtractPlainObject<T>];
114
120
 
115
121
  /**
116
122
  * Creates an object from `x` with keys `k` if `f(x[k])` returns `true`.
117
123
  * If `x` is not a plain object, or there's no passed props, returns `undefined`.
118
124
  */
119
- export const toPlainObjectOf = <T>(x: unknown, f: (v: unknown) => v is T): { [key: PropertyKey]: T } | _ => {
125
+ export const toPlainObjectOf = <T, U extends ExtractPlainObjectValue<T>>(
126
+ x: T,
127
+ f: (v: ExtractPlainObjectValue<T>) => v is U
128
+ ): Record<PropertyKey, U> | _ => {
120
129
  if (isPlainObject(x)) {
121
130
  let index = -1;
122
131
  let props = Object.keys(x);
123
132
  let length = props.length;
124
- let result: { [key: PropertyKey]: T } | _;
133
+ let result: Record<PropertyKey, U> | _;
125
134
 
126
135
  while (++index < length) {
127
- let key = props[index];
136
+ let key = props[index] as keyof typeof x;
128
137
  let value = x[key];
129
138
  if (f(value)) {
130
139
  (result ??= {})[key] = value;
@@ -136,7 +145,7 @@ export const toPlainObjectOf = <T>(x: unknown, f: (v: unknown) => v is T): { [ke
136
145
  };
137
146
 
138
147
  /** Filter props from object `x` whose values are `true`. */
139
- export const toPlainObjectOfTrue = (x: unknown): { [key: PropertyKey]: true } | _ => toPlainObjectOf(x, isTrue);
148
+ export const toPlainObjectOfTrue = (x: unknown): Record<PropertyKey, true> | _ => toPlainObjectOf(x, isTrue);
140
149
 
141
150
  /**
142
151
  * Returns `x` if `x` is string, otherwise returns `''` (empty string) if