0
# Immutable Objects
1
2
Non-mutating object manipulation functions for property selection, modification, and merging operations. These utilities enable functional programming patterns while maintaining type safety and are ideal for updating Solid.js signals containing object state.
3
4
## Capabilities
5
6
### Property Selection
7
8
Functions for creating new objects with selected or excluded properties.
9
10
```typescript { .api }
11
/**
12
* Create a new subset object without the provided keys
13
* @param object - Original object
14
* @param keys - Keys to exclude
15
* @returns New object without specified keys
16
*/
17
function omit<O extends object, K extends keyof O>(object: O, ...keys: K[]): Omit<O, K>;
18
19
/**
20
* Create a new subset object with only the provided keys
21
* @param object - Original object
22
* @param keys - Keys to include
23
* @returns New object with only specified keys
24
*/
25
function pick<O extends object, K extends keyof O>(object: O, ...keys: K[]): Pick<O, K>;
26
```
27
28
**Usage Examples:**
29
30
```typescript
31
import { omit, pick } from "@solid-primitives/utils/immutable";
32
import { createSignal } from "solid-js";
33
34
const [user, setUser] = createSignal({
35
id: 1,
36
name: "Alice",
37
email: "alice@example.com",
38
password: "secret",
39
role: "admin"
40
});
41
42
// Remove sensitive data
43
setUser(current => omit(current, "password"));
44
// { id: 1, name: "Alice", email: "alice@example.com", role: "admin" }
45
46
// Select only public fields
47
const publicData = pick(user(), "id", "name");
48
// { id: 1, name: "Alice" }
49
```
50
51
### Property Access
52
53
Functions for accessing nested object properties safely.
54
55
```typescript { .api }
56
/**
57
* Get a single property value of an object by specifying a path to it
58
*/
59
function get<O extends object, K extends keyof O>(obj: O, key: K): O[K];
60
function get<O extends object, K1 extends keyof O, K2 extends keyof O[K1]>(
61
obj: O,
62
k1: K1,
63
k2: K2
64
): O[K1][K2];
65
function get<
66
O extends object,
67
K1 extends keyof O,
68
K2 extends keyof O[K1],
69
K3 extends keyof O[K1][K2]
70
>(obj: O, k1: K1, k2: K2, k3: K3): O[K1][K2][K3];
71
function get<
72
O extends object,
73
K1 extends keyof O,
74
K2 extends keyof O[K1],
75
K3 extends keyof O[K1][K2],
76
K4 extends keyof O[K1][K2][K3]
77
>(obj: O, k1: K1, k2: K2, k3: K3, k4: K4): O[K1][K2][K3][K4];
78
function get<
79
O extends object,
80
K1 extends keyof O,
81
K2 extends keyof O[K1],
82
K3 extends keyof O[K1][K2],
83
K4 extends keyof O[K1][K2][K3],
84
K5 extends keyof O[K1][K2][K3][K4]
85
>(obj: O, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5): O[K1][K2][K3][K4][K5];
86
function get<
87
O extends object,
88
K1 extends keyof O,
89
K2 extends keyof O[K1],
90
K3 extends keyof O[K1][K2],
91
K4 extends keyof O[K1][K2][K3],
92
K5 extends keyof O[K1][K2][K3][K4],
93
K6 extends keyof O[K1][K2][K3][K4][K5]
94
>(obj: O, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6): O[K1][K2][K3][K4][K5][K6];
95
```
96
97
**Usage Examples:**
98
99
```typescript
100
import { get } from "@solid-primitives/utils/immutable";
101
102
const data = {
103
user: {
104
profile: {
105
settings: {
106
theme: "dark",
107
notifications: true
108
}
109
}
110
}
111
};
112
113
// Deep property access
114
const theme = get(data, "user", "profile", "settings", "theme"); // "dark"
115
const notifications = get(data, "user", "profile", "settings", "notifications"); // true
116
117
// Single level access
118
const profile = get(data, "user", "profile");
119
```
120
121
### Property Updates
122
123
Functions for updating object properties immutably with support for deep nested updates.
124
125
```typescript { .api }
126
/**
127
* Change single value in an object by key. Allows accessing nested objects by passing multiple keys.
128
* Performs a shallow copy of each accessed object.
129
* @param object - Original source object
130
* @param keys - Keys of sequential accessed objects
131
* @param setter - Value to set or setter function
132
* @returns New object with updated value
133
*/
134
function update<O extends object, K extends keyof O, V>(
135
object: O,
136
key: K,
137
setter: UpdateSetter<O, K, V>
138
): ModifyValue<O, K, V>;
139
140
function update<O extends object, K0 extends keyof O, K1 extends keyof O[K0], V>(
141
object: O,
142
k0: K0,
143
k1: K1,
144
setter: UpdateSetter<O[K0], K1, V>
145
): ModifyValue<O, K0, ModifyValue<O[K0], K1, V>>;
146
147
function update<
148
O extends object,
149
K0 extends keyof O,
150
K1 extends keyof O[K0],
151
K2 extends keyof O[K0][K1],
152
V
153
>(
154
object: O,
155
k0: K0,
156
k1: K1,
157
k2: K2,
158
setter: UpdateSetter<O[K0][K1], K2, V>
159
): ModifyValue<O, K0, ModifyValue<O[K0], K1, ModifyValue<O[K0][K1], K2, V>>>;
160
161
function update<
162
O extends object,
163
K0 extends keyof O,
164
K1 extends keyof O[K0],
165
K2 extends keyof O[K0][K1],
166
K3 extends keyof O[K0][K1][K2],
167
V
168
>(
169
object: O,
170
k0: K0,
171
k1: K1,
172
k2: K2,
173
k3: K3,
174
setter: UpdateSetter<O[K0][K1][K2], K3, V>
175
): ModifyValue<
176
O,
177
K0,
178
ModifyValue<O[K0], K1, ModifyValue<O[K0][K1], K2, ModifyValue<O[K0][K1][K2], K3, V>>>
179
>;
180
181
function update<
182
O extends object,
183
K0 extends keyof O,
184
K1 extends keyof O[K0],
185
K2 extends keyof O[K0][K1],
186
K3 extends keyof O[K0][K1][K2],
187
K4 extends keyof O[K0][K1][K2][K3],
188
V
189
>(
190
object: O,
191
k0: K0,
192
k1: K1,
193
k2: K2,
194
k3: K3,
195
k4: K4,
196
setter: UpdateSetter<O[K0][K1][K2][K3], K4, V>
197
): ModifyValue<
198
O,
199
K0,
200
ModifyValue<
201
O[K0],
202
K1,
203
ModifyValue<O[K0][K1], K2, ModifyValue<O[K0][K1][K2], K3, ModifyValue<O[K0][K1][K2][K3], K4, V>>>
204
>
205
>;
206
207
type UpdateSetter<O, K extends keyof O, V> = V | ((prev: O[K]) => V);
208
```
209
210
**Usage Examples:**
211
212
```typescript
213
import { update } from "@solid-primitives/utils/immutable";
214
import { createSignal } from "solid-js";
215
216
const [state, setState] = createSignal({
217
user: {
218
name: "Alice",
219
settings: {
220
theme: "light",
221
notifications: {
222
email: true,
223
push: false
224
}
225
}
226
},
227
count: 0
228
});
229
230
// Simple update
231
setState(current => update(current, "count", 1));
232
233
// Deep nested update with value
234
setState(current => update(current, "user", "settings", "theme", "dark"));
235
236
// Deep nested update with function
237
setState(current => update(
238
current,
239
"user", "settings", "notifications", "email",
240
prev => !prev
241
));
242
243
// Function-based update
244
setState(current => update(current, "count", prev => prev + 1));
245
```
246
247
### Object Splitting
248
249
Functions for splitting objects into multiple subset objects.
250
251
```typescript { .api }
252
/**
253
* Split object properties by keys into multiple object copies with a subset of selected properties
254
* @param object - Original object
255
* @param keys - Keys to pick from the source, or arrays of keys for multiple splits
256
* @returns Array of subset objects
257
*/
258
function split<T extends object, K extends keyof T>(
259
object: T,
260
...keys: K[]
261
): [Pick<T, K>, Omit<T, K>];
262
263
function split<T extends object, K1 extends keyof T, K2 extends keyof T>(
264
object: T,
265
...keys: [K1[], K2[]]
266
): [Pick<T, K1>, Pick<T, K2>, Omit<T, K1 | K2>];
267
268
function split<T extends object, K1 extends keyof T, K2 extends keyof T, K3 extends keyof T>(
269
object: T,
270
...keys: [K1[], K2[], K3[]]
271
): [Pick<T, K1>, Pick<T, K2>, Pick<T, K3>, Omit<T, K1 | K2 | K3>];
272
```
273
274
**Usage Examples:**
275
276
```typescript
277
import { split } from "@solid-primitives/utils/immutable";
278
279
const user = {
280
id: 1,
281
name: "Alice",
282
email: "alice@example.com",
283
password: "secret",
284
role: "admin",
285
createdAt: new Date()
286
};
287
288
// Simple split - public vs private
289
const [publicData, privateData] = split(user, "id", "name", "email");
290
// publicData: { id: 1, name: "Alice", email: "alice@example.com" }
291
// privateData: { password: "secret", role: "admin", createdAt: Date }
292
293
// Multiple splits
294
const [identity, security, metadata, rest] = split(
295
user,
296
["id", "name"],
297
["password", "role"],
298
["createdAt"]
299
);
300
// identity: { id: 1, name: "Alice" }
301
// security: { password: "secret", role: "admin" }
302
// metadata: { createdAt: Date }
303
// rest: { email: "alice@example.com" }
304
```
305
306
### Object Merging
307
308
Functions for merging multiple objects into a single object.
309
310
```typescript { .api }
311
/**
312
* Merges multiple objects into a single one. Only the first level of properties is merged.
313
* An alternative to { ...a, ...b, ...c }
314
* @param objects - Objects to merge
315
* @returns New merged object
316
*/
317
function merge<A extends object, B extends object>(a: A, b: B): Modify<A, B>;
318
function merge<A extends object, B extends object, C extends object>(
319
a: A,
320
b: B,
321
c: C
322
): Modify<Modify<A, B>, C>;
323
function merge<A extends object, B extends object, C extends object, D extends object>(
324
a: A,
325
b: B,
326
c: C,
327
d: D
328
): Modify<Modify<Modify<A, B>, C>, D>;
329
function merge<
330
A extends object,
331
B extends object,
332
C extends object,
333
D extends object,
334
E extends object
335
>(a: A, b: B, c: C, d: D, e: E): Modify<Modify<Modify<Modify<A, B>, C>, D>, E>;
336
function merge<
337
A extends object,
338
B extends object,
339
C extends object,
340
D extends object,
341
E extends object,
342
F extends object
343
>(a: A, b: B, c: C, d: D, e: E, f: F): Modify<Modify<Modify<Modify<Modify<A, B>, C>, D>, E>, F>;
344
```
345
346
**Usage Examples:**
347
348
```typescript
349
import { merge } from "@solid-primitives/utils/immutable";
350
351
const defaults = { theme: "light", lang: "en" };
352
const userPrefs = { theme: "dark", fontSize: 14 };
353
const systemPrefs = { highContrast: false };
354
355
const finalPrefs = merge(defaults, userPrefs, systemPrefs);
356
// { theme: "dark", lang: "en", fontSize: 14, highContrast: false }
357
```
358
359
### Copying Utilities
360
361
Functions for creating shallow copies of objects and arrays.
362
363
```typescript { .api }
364
/**
365
* Make shallow copy of an array
366
* @param array - Array to copy
367
* @returns New array with same elements
368
*/
369
function shallowArrayCopy<T>(array: readonly T[]): T[];
370
371
/**
372
* Make shallow copy of an object
373
* @param object - Object to copy
374
* @returns New object with same properties
375
*/
376
function shallowObjectCopy<T extends object>(object: T): T;
377
378
/**
379
* Make shallow copy of an array/object
380
* @param source - Array or object to copy
381
* @returns New copy of the source
382
*/
383
function shallowCopy<T extends object>(source: T): T;
384
385
/**
386
* Apply mutations to an array without changing the original
387
* @param array - Original array
388
* @param mutator - Function that applies mutations to the copy
389
* @returns New array with mutations applied
390
*/
391
function withArrayCopy<T>(array: readonly T[], mutator: (copy: T[]) => void): T[];
392
393
/**
394
* Apply mutations to an object without changing the original
395
* @param object - Original object
396
* @param mutator - Function that applies mutations to the copy
397
* @returns New object with mutations applied
398
*/
399
function withObjectCopy<T extends object>(object: T, mutator: (copy: T) => void): T;
400
401
/**
402
* Apply mutations to an object/array without changing the original
403
* @param source - Original object or array
404
* @param mutator - Function that applies mutations to the copy
405
* @returns New copy with mutations applied
406
*/
407
function withCopy<T extends object>(source: T, mutator: (copy: T) => void): T;
408
```
409
410
**Usage Examples:**
411
412
```typescript
413
import {
414
shallowArrayCopy, shallowObjectCopy, withArrayCopy, withObjectCopy
415
} from "@solid-primitives/utils/immutable";
416
417
// Shallow copying
418
const originalArray = [1, 2, 3];
419
const copiedArray = shallowArrayCopy(originalArray); // [1, 2, 3]
420
421
const originalObject = { a: 1, b: 2 };
422
const copiedObject = shallowObjectCopy(originalObject); // { a: 1, b: 2 }
423
424
// Mutating copies
425
const numbers = [1, 2, 3];
426
const reversed = withArrayCopy(numbers, arr => arr.reverse()); // [3, 2, 1]
427
428
const user = { name: "Alice", age: 30 };
429
const updated = withObjectCopy(user, obj => {
430
obj.age = 31;
431
obj.status = "active";
432
}); // { name: "Alice", age: 31, status: "active" }
433
```
434
435
## Types
436
437
```typescript { .api }
438
type UpdateSetter<O, K extends keyof O, V> = V | ((prev: O[K]) => V);
439
type ModifyValue<O, K extends keyof O, V> = Omit<O, K> & { [key in K]: V };
440
type Modify<T, R> = Omit<T, keyof R> & R;
441
```