strip-undefined-values 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # strip-undefined-values
2
+
3
+ Remove `undefined` values from an object before sending to APIs, databases, or serializers.
4
+
5
+ Zero dependencies. Fully typed. Tiny. Shallow.
6
+
7
+ ```ts
8
+ import { stripUndefined } from "strip-undefined-values"
9
+
10
+ stripUndefined({ name: "Tomas", age: undefined, active: true })
11
+ // => { name: "Tomas", active: true }
12
+ ```
13
+
14
+ ---
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install strip-undefined-values
20
+ ```
21
+
22
+ ```bash
23
+ pnpm add strip-undefined-values
24
+ ```
25
+
26
+ ```bash
27
+ yarn add strip-undefined-values
28
+ ```
29
+
30
+ ---
31
+
32
+ ## API
33
+
34
+ ```ts
35
+ function stripUndefined<T extends Record<string, any>>(obj: T): StripUndefined<T>
36
+ ```
37
+
38
+ Removes own properties whose value is strictly `undefined`.
39
+ Returns a **new object** — does **not** mutate the input.
40
+ Nested objects are not traversed (shallow only).
41
+
42
+ | Value | Kept? |
43
+ | ----------- | ----- |
44
+ | `null` | Yes |
45
+ | `false` | Yes |
46
+ | `0` | Yes |
47
+ | `""` | Yes |
48
+ | `NaN` | Yes |
49
+ | `undefined` | **No**|
50
+
51
+ ---
52
+
53
+ ## TypeScript
54
+
55
+ The return type `StripUndefined<T>` automatically excludes keys whose type includes `undefined`:
56
+
57
+ ```ts
58
+ type Input = { name: string; age: number | undefined; active: boolean }
59
+ type Output = StripUndefined<Input>
60
+ // ^? { name: string; active: boolean }
61
+ ```
62
+
63
+ This is intentionally conservative — the type is stricter than runtime so you can never accidentally access a possibly-undefined property on the result.
64
+
65
+ You can also use `StripUndefined<T>` standalone as a utility type:
66
+
67
+ ```ts
68
+ import type { StripUndefined } from "strip-undefined-values"
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Common Use Cases
74
+
75
+ ### API payloads / PATCH requests
76
+
77
+ ```ts
78
+ await fetch("/api/user", {
79
+ method: "PATCH",
80
+ body: JSON.stringify(stripUndefined({ name, email, age }))
81
+ })
82
+ ```
83
+
84
+ ### Query parameters
85
+
86
+ ```ts
87
+ const params = stripUndefined({ page, search, sort })
88
+ const url = `/items?${new URLSearchParams(params)}`
89
+ ```
90
+
91
+ ### Prisma / database updates
92
+
93
+ ```ts
94
+ await prisma.user.update({
95
+ where: { id },
96
+ data: stripUndefined({ name, email, bio })
97
+ })
98
+ ```
99
+
100
+ ### GraphQL variables
101
+
102
+ ```ts
103
+ const { data } = await client.query({
104
+ query: GET_USERS,
105
+ variables: stripUndefined({ first, after, filter })
106
+ })
107
+ ```
108
+
109
+ ### Optional form fields
110
+
111
+ ```ts
112
+ const formData = stripUndefined({
113
+ title: form.title,
114
+ description: form.description || undefined,
115
+ category: form.category || undefined,
116
+ })
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Comparison
122
+
123
+ | Approach | Typed? | Deps | Deep? | Mutates? |
124
+ | --- | --- | --- | --- | --- |
125
+ | **`strip-undefined-values`** | **Yes** | **0** | No | No |
126
+ | `lodash.omitBy` | Partial | 1 | No | No |
127
+ | `Object.fromEntries(…filter…)` | No | 0 | No | No |
128
+ | `remove-undefined-objects` | No | 1+ | Yes | No |
129
+ | Manual `delete` | No | 0 | No | **Yes** |
130
+
131
+ ---
132
+
133
+ ## License
134
+
135
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stripUndefined = stripUndefined;
4
+ /**
5
+ * Remove own properties whose value is strictly `undefined` from an object.
6
+ *
7
+ * Returns a **new** plain object — the input is never mutated.
8
+ * Only top-level properties are checked (shallow). Nested objects are
9
+ * copied by reference and left untouched.
10
+ *
11
+ * Values like `null`, `false`, `0`, and `""` are kept.
12
+ *
13
+ * @typeParam T - The source object type
14
+ * @param obj - The object to strip `undefined` values from
15
+ * @returns A new object without any `undefined`-valued properties
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { stripUndefined } from "strip-undefined-values"
20
+ *
21
+ * stripUndefined({ name: "Tomas", age: undefined, active: true })
22
+ * // => { name: "Tomas", active: true }
23
+ * ```
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * // Safe for API payloads
28
+ * await fetch("/api/user", {
29
+ * method: "PATCH",
30
+ * body: JSON.stringify(stripUndefined({ name, email, age }))
31
+ * })
32
+ * ```
33
+ *
34
+ * @see {@link StripUndefined} for the companion utility type
35
+ * @since 1.0.0
36
+ */
37
+ function stripUndefined(obj) {
38
+ const result = {};
39
+ for (const key in obj) {
40
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
41
+ const value = obj[key];
42
+ if (value !== undefined) {
43
+ result[key] = value;
44
+ }
45
+ }
46
+ }
47
+ return result;
48
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Mapped type that removes keys whose value type includes `undefined`.
3
+ *
4
+ * @remarks
5
+ * This is intentionally conservative: if a key is typed as `T | undefined`,
6
+ * it is excluded from the result type entirely. At runtime the key is only
7
+ * removed when the value *actually is* `undefined`, so the type is stricter
8
+ * than the runtime behavior. This keeps downstream code safe — you will never
9
+ * accidentally access a possibly-undefined property on the result.
10
+ *
11
+ * @typeParam T - The source object type
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * type Input = { name: string; age: number | undefined }
16
+ * type Output = StripUndefined<Input>
17
+ * // ^? { name: string }
18
+ * ```
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ export type StripUndefined<T extends Record<string, any>> = {
23
+ [K in keyof T as undefined extends T[K] ? never : K]: Exclude<T[K], undefined>;
24
+ };
25
+ /**
26
+ * Remove own properties whose value is strictly `undefined` from an object.
27
+ *
28
+ * Returns a **new** plain object — the input is never mutated.
29
+ * Only top-level properties are checked (shallow). Nested objects are
30
+ * copied by reference and left untouched.
31
+ *
32
+ * Values like `null`, `false`, `0`, and `""` are kept.
33
+ *
34
+ * @typeParam T - The source object type
35
+ * @param obj - The object to strip `undefined` values from
36
+ * @returns A new object without any `undefined`-valued properties
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { stripUndefined } from "strip-undefined-values"
41
+ *
42
+ * stripUndefined({ name: "Tomas", age: undefined, active: true })
43
+ * // => { name: "Tomas", active: true }
44
+ * ```
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * // Safe for API payloads
49
+ * await fetch("/api/user", {
50
+ * method: "PATCH",
51
+ * body: JSON.stringify(stripUndefined({ name, email, age }))
52
+ * })
53
+ * ```
54
+ *
55
+ * @see {@link StripUndefined} for the companion utility type
56
+ * @since 1.0.0
57
+ */
58
+ export declare function stripUndefined<T extends Record<string, any>>(obj: T): StripUndefined<T>;
package/dist/index.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Remove own properties whose value is strictly `undefined` from an object.
3
+ *
4
+ * Returns a **new** plain object — the input is never mutated.
5
+ * Only top-level properties are checked (shallow). Nested objects are
6
+ * copied by reference and left untouched.
7
+ *
8
+ * Values like `null`, `false`, `0`, and `""` are kept.
9
+ *
10
+ * @typeParam T - The source object type
11
+ * @param obj - The object to strip `undefined` values from
12
+ * @returns A new object without any `undefined`-valued properties
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { stripUndefined } from "strip-undefined-values"
17
+ *
18
+ * stripUndefined({ name: "Tomas", age: undefined, active: true })
19
+ * // => { name: "Tomas", active: true }
20
+ * ```
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * // Safe for API payloads
25
+ * await fetch("/api/user", {
26
+ * method: "PATCH",
27
+ * body: JSON.stringify(stripUndefined({ name, email, age }))
28
+ * })
29
+ * ```
30
+ *
31
+ * @see {@link StripUndefined} for the companion utility type
32
+ * @since 1.0.0
33
+ */
34
+ export function stripUndefined(obj) {
35
+ const result = {};
36
+ for (const key in obj) {
37
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
38
+ const value = obj[key];
39
+ if (value !== undefined) {
40
+ result[key] = value;
41
+ }
42
+ }
43
+ }
44
+ return result;
45
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "strip-undefined-values",
3
+ "version": "1.0.0",
4
+ "description": "Remove undefined properties from an object. Fully typed. Zero dependencies.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "sideEffects": false,
20
+ "keywords": [
21
+ "strip",
22
+ "undefined",
23
+ "remove undefined",
24
+ "omit undefined",
25
+ "clean object",
26
+ "filter undefined",
27
+ "sanitize object",
28
+ "api payload",
29
+ "typescript",
30
+ "utility",
31
+ "zero-dependency"
32
+ ],
33
+ "author": "Tomas",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/tomahg/strip-undefined-values"
38
+ },
39
+ "homepage": "https://github.com/tomahg/strip-undefined-values#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/tomahg/strip-undefined-values/issues"
42
+ },
43
+ "engines": {
44
+ "node": ">=14"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc && tsc --module commonjs --outDir dist/cjs --declaration false && node -e \"fs.renameSync('dist/cjs/index.js','dist/index.cjs')\" && node -e \"fs.rmSync('dist/cjs',{recursive:true})\"",
48
+ "clean": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\"",
49
+ "test": "vitest run",
50
+ "test:watch": "vitest",
51
+ "prepublishOnly": "npm run build"
52
+ },
53
+ "devDependencies": {
54
+ "typescript": "^5.0.0",
55
+ "vitest": "^3.0.0"
56
+ }
57
+ }