mutate-cow 8.1.0 → 9.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 CHANGED
@@ -21,7 +21,7 @@ No cows were harmed in the making of this code.
21
21
 
22
22
  ## API
23
23
 
24
- ### const ctx = mutate(source, /* strict = */ false)
24
+ ### const ctx = mutate(source)
25
25
 
26
26
  Returns a "context" object which can modify a copy of `source`.
27
27
 
@@ -30,11 +30,7 @@ const foo = deepFreeze({bar: {baz: []}});
30
30
  const ctx = mutate(foo);
31
31
  ````
32
32
 
33
- By default, you can mutate primitves, arrays, and plain objects. However, if `strict` is set to true, the following features are enabled:
34
-
35
- * All property descriptors from the immutable object are preserved in the copy.
36
- * All extensibility information from the immutable object is preserved in the copy. Combined with the above point, this means that sealed objects stay sealed and frozen objects stay frozen.
37
- * Class instances are supported for mutation.
33
+ You can mutate primitives, arrays, and plain objects. However, note that `null` prototypes and frozenness are not preserved.
38
34
 
39
35
  ### ctx.read()
40
36
 
@@ -75,6 +71,8 @@ Sets the given `path` to `value` on the current working copy. Returns `ctx`.
75
71
 
76
72
  Passing zero property names (i.e., only a value) sets the current context's value.
77
73
 
74
+ Only own properties are written.
75
+
78
76
  ```js
79
77
  const qux = ['qux'];
80
78
  // these all do the same thing
@@ -84,6 +82,28 @@ ctx.set('bar', 'baz', qux);
84
82
  ctx.get('bar').set({baz: qux});
85
83
  ctx.get('bar').set('baz', qux);
86
84
  ctx.get('bar', 'baz').set(qux);
85
+
86
+ // sets the own property '__proto__', not the prototype
87
+ ctx.set('__proto__', {});
88
+ ```
89
+
90
+ ### ctx.merge(object)
91
+
92
+ Recursively merges a plain `object` into the current working copy, as if `set` were called with each of its own enumerable key/value pairs. Returns `ctx`.
93
+
94
+ Keys that aren't defined in `object` are preserved on the working copy. Values that aren't plain objects (including arrays, class instances, and primitives) replace the existing value.
95
+
96
+ Only own properties are written.
97
+
98
+ ```js
99
+ ctx.merge({bar: {qux: 1}});
100
+ ctx.read().bar.qux === 1;
101
+ ctx.read().bar.baz === foo.bar.baz; // other properties are preserved
102
+
103
+ // these all do the same thing
104
+ ctx.merge({bar: {qux: 1}});
105
+ ctx.get('bar').merge({qux: 1});
106
+ ctx.set('bar', 'qux', 1);
87
107
  ```
88
108
 
89
109
  ### ctx.update(...path: [prop1, ...], updater)
@@ -131,11 +151,10 @@ Returns a boolean indicating whether `ctx` has been revoked.
131
151
 
132
152
  ### ctx.final()
133
153
 
134
- This is the same as `read`, except it also revokes the context, and in strict mode restores all property descriptors and extensibility information. This is what you call to get the final copy.
154
+ This is the same as `read`, except it also revokes the context. This is what you call to get the final copy.
135
155
 
136
156
  ```js
137
- const copy = mutate(foo, /* strict = */ true).set('bar', 'baz', 'qux').final();
138
- Object.isFrozen(copy) === true; // since `foo` was frozen, `copy` will be too
157
+ const copy = mutate(foo).set('bar', 'baz', 'qux').final();
139
158
  ````
140
159
 
141
160
  ### ctx.finalRoot()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mutate-cow",
3
- "version": "8.1.0",
3
+ "version": "9.0.0",
4
4
  "description": "Update immutable objects as if they were mutable with copy-on-write",
5
5
  "keywords": [
6
6
  "immutable",
@@ -10,6 +10,11 @@
10
10
  ],
11
11
  "main": "src/index.js",
12
12
  "types": "types/index.d.ts",
13
+ "files": [
14
+ "src/index.js",
15
+ "src/index.js.flow",
16
+ "types/index.d.ts"
17
+ ],
13
18
  "license": "MIT",
14
19
  "author": "Michael Wiencek <mwtuea@gmail.com>",
15
20
  "repository": {
@@ -18,15 +23,15 @@
18
23
  },
19
24
  "devDependencies": {
20
25
  "benchmark": "2.1.4",
21
- "flow-bin": "0.290.0",
22
- "immer": "10.1.1",
23
- "mutative": "1.2.0",
24
- "tsd": "0.29.0"
26
+ "flow-bin": "0.329.0",
27
+ "immer": "11.1.18",
28
+ "mutative": "1.3.0",
29
+ "tsd": "0.33.0"
25
30
  },
26
31
  "sideEffects": false,
27
32
  "type": "module",
28
33
  "scripts": {
29
34
  "test": "node --test --experimental-test-coverage test/index.js"
30
35
  },
31
- "packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c"
36
+ "packageManager": "yarn@4.18.0"
32
37
  }
package/src/index.js CHANGED
@@ -9,66 +9,59 @@ const EMPTY_OBJECT = Object.freeze({});
9
9
 
10
10
  const NATIVE_CODE_REGEXP = /^function \w*\(\) \{\s*\[native code\]\s*\}$/m;
11
11
 
12
+ const TYPE_PRIMITIVE = 1;
13
+ const TYPE_PLAIN_OBJECT = 2;
14
+ const TYPE_PLAIN_ARRAY = 3;
15
+ const TYPE_UNSUPPORTED = 4;
16
+
12
17
  const STATUS_NONE = 1;
13
18
  const STATUS_MUTABLE = 2;
14
19
  const STATUS_REVOKED = 3;
15
20
  const STATUS_STALE = 4;
16
21
 
17
- function isPrimitive(value) {
22
+ function getValueType(value) {
18
23
  if (value === null) {
19
- return true;
24
+ return TYPE_PRIMITIVE;
20
25
  }
21
26
  const type = typeof value;
22
- return (type !== 'function' && type !== 'object');
27
+ if (type !== 'object') {
28
+ return type === 'function' ? TYPE_UNSUPPORTED : TYPE_PRIMITIVE;
29
+ }
30
+ const proto = Object.getPrototypeOf(value);
31
+ if (proto === Object.prototype) {
32
+ return TYPE_PLAIN_OBJECT;
33
+ } else if (proto === Array.prototype) {
34
+ return Array.isArray(value) ? TYPE_PLAIN_ARRAY : TYPE_UNSUPPORTED;
35
+ } else if (Array.isArray(value)) {
36
+ return (proto !== null && isNativePrototype(proto, 'Array'))
37
+ ? TYPE_PLAIN_ARRAY
38
+ : TYPE_UNSUPPORTED;
39
+ } else if (proto === null) {
40
+ return TYPE_PLAIN_OBJECT;
41
+ }
42
+ return (
43
+ Object.getPrototypeOf(proto) === null &&
44
+ isNativePrototype(proto, 'Object')
45
+ ) ? TYPE_PLAIN_OBJECT : TYPE_UNSUPPORTED;
23
46
  }
24
47
 
25
- function isCloneableObject(object) {
26
- if (typeof object === 'function') {
27
- return false;
28
- }
29
- let proto = Object.getPrototypeOf(object);
30
- while (proto) {
31
- let ctor = proto.constructor;
32
- if (ctor) {
33
- // A Generator object's constructor is an object.
34
- if (typeof ctor === 'object') {
35
- ctor = ctor.constructor;
36
- }
37
- if (
38
- typeof ctor === 'function' &&
39
- ctor.name !== 'Array' &&
40
- ctor.name !== 'Object' &&
41
- NATIVE_CODE_REGEXP.test(Function.prototype.toString.call(ctor))
42
- ) {
43
- return false;
44
- }
45
- }
46
- proto = Object.getPrototypeOf(proto);
47
- }
48
- return true;
49
- }
50
-
51
- function printConstructor(object) {
52
- const ctor = object.constructor;
53
- switch (typeof ctor) {
54
- case 'function':
55
- return ctor.name;
56
- case 'object':
57
- return Object.prototype.toString.call(ctor);
58
- default:
59
- return '[primitive constructor]';
60
- }
48
+ function isNativePrototype(proto, name) {
49
+ const ctor = proto.constructor;
50
+ return (
51
+ typeof ctor === 'function' &&
52
+ ctor.name === name &&
53
+ ctor.prototype === proto &&
54
+ NATIVE_CODE_REGEXP.test(Function.prototype.toString.call(ctor))
55
+ );
61
56
  }
62
57
 
63
- function restoreDescriptors(copy, changedDescriptors) {
64
- for (let i = 0; i < changedDescriptors.length; i++) {
65
- const [name, origDesc] = changedDescriptors[i];
66
- const descriptor = Object.getOwnPropertyDescriptor(copy, name);
67
- if (descriptor) {
68
- Object.assign(descriptor, origDesc);
69
- Reflect.defineProperty(copy, name, descriptor);
70
- }
71
- }
58
+ function setProtoProperty(object, value) {
59
+ Reflect.defineProperty(object, '__proto__', {
60
+ value,
61
+ writable: true,
62
+ enumerable: true,
63
+ configurable: true,
64
+ });
72
65
  }
73
66
 
74
67
  export class CowContext {
@@ -87,32 +80,33 @@ export class CowContext {
87
80
  }
88
81
  if (!this._result) {
89
82
  const source = this._getSource();
90
- if (isPrimitive(source)) {
91
- this._result = forceObject ? {} : source;
92
- } else if (!isCloneableObject(source)) {
93
- throw new Error(
94
- printConstructor(source) +
95
- ' objects are not supported for cloning.',
96
- );
97
- } else {
98
- this._result = this._cloneSourceObject(source);
83
+ switch (getValueType(source)) {
84
+ case TYPE_PLAIN_OBJECT:
85
+ this._result = {...source};
86
+ break;
87
+ case TYPE_PLAIN_ARRAY:
88
+ this._result = source.slice();
89
+ break;
90
+ case TYPE_PRIMITIVE:
91
+ this._result = forceObject ? {} : source;
92
+ break;
93
+ default:
94
+ throw new Error('Only plain objects and arrays can be cloned.');
99
95
  }
100
96
  }
101
97
  const parent = this._parent;
102
98
  if (parent) {
103
99
  parent._copyForWrite(/* forceObject = */ true);
104
- parent._result[this._prop] = this._result;
100
+ const prop = this._prop;
101
+ if (prop === '__proto__') {
102
+ setProtoProperty(parent._result, this._result);
103
+ } else {
104
+ parent._result[prop] = this._result;
105
+ }
105
106
  }
106
107
  this._status = STATUS_MUTABLE;
107
108
  }
108
109
 
109
- _cloneSourceObject(source) {
110
- if (Array.isArray(source)) {
111
- return source.slice();
112
- }
113
- return {...source};
114
- }
115
-
116
110
  _getPropValue(prop) {
117
111
  return Reflect.get(this._read() ?? EMPTY_OBJECT, prop);
118
112
  }
@@ -196,7 +190,11 @@ export class CowContext {
196
190
 
197
191
  _set(prop, newValue) {
198
192
  this._copyForWrite(/* forceObject = */ true);
199
- this._result[prop] = newValue;
193
+ if (prop === '__proto__') {
194
+ setProtoProperty(this._result, newValue);
195
+ } else {
196
+ this._result[prop] = newValue;
197
+ }
200
198
 
201
199
  // Child source values must be invalidated, because they can
202
200
  // reference a previous copy we made.
@@ -248,6 +246,44 @@ export class CowContext {
248
246
  return this;
249
247
  }
250
248
 
249
+ _getForMerge(prop) {
250
+ const child = this._get(prop);
251
+ if (!Object.hasOwn(this._read() ?? EMPTY_OBJECT, prop)) {
252
+ child._source = null;
253
+ child._status = STATUS_NONE;
254
+ child._setAllChildrenAsStale();
255
+ }
256
+ return child;
257
+ }
258
+
259
+ _merge(object) {
260
+ if (Array.isArray(this._read())) {
261
+ throw new Error('`merge` cannot be used to patch an array.');
262
+ }
263
+ const keys = Reflect.ownKeys(object);
264
+ for (let i = 0; i < keys.length; i++) {
265
+ const key = keys[i];
266
+ if (!Object.getOwnPropertyDescriptor(object, key).enumerable) {
267
+ continue;
268
+ }
269
+ const newValue = Reflect.get(object, key);
270
+ if (getValueType(newValue) === TYPE_PLAIN_OBJECT) {
271
+ this._getForMerge(key)._merge(newValue);
272
+ } else {
273
+ this._setIfChanged(key, newValue);
274
+ }
275
+ }
276
+ }
277
+
278
+ merge(object) {
279
+ this._throwIfRevoked();
280
+ if (getValueType(object) !== TYPE_PLAIN_OBJECT) {
281
+ throw new Error('`merge` must be called with a plain object.');
282
+ }
283
+ this._merge(object);
284
+ return this;
285
+ }
286
+
251
287
  update(...args) {
252
288
  const updater = args.pop();
253
289
  updater(this.get(...args));
@@ -330,106 +366,6 @@ export class CowContext {
330
366
  }
331
367
  }
332
368
 
333
- class CowContextStrict extends CowContext {
334
- constructor(source, prop, parent) {
335
- super(source, prop, parent);
336
- this._callbacks = null;
337
- }
338
-
339
- _replace(value) {
340
- super._replace(value);
341
- if (!this._parent) {
342
- this._callbacks = null;
343
- }
344
- }
345
-
346
- _setStale() {
347
- super._setStale();
348
- this._callbacks = null;
349
- }
350
-
351
- _cloneSourceObject(source) {
352
- if (!this._callbacks) {
353
- this._callbacks = [];
354
- }
355
- const proto = Object.getPrototypeOf(source);
356
- let changedDescriptors = [];
357
- let copy;
358
- if (Array.isArray(source)) {
359
- copy = Reflect.construct(Array, source, proto.constructor);
360
- } else {
361
- copy = Object.create(proto);
362
- }
363
- const ownKeys = Reflect.ownKeys(source);
364
- for (let i = 0; i < ownKeys.length; i++) {
365
- const key = ownKeys[i];
366
- const descriptor = Object.getOwnPropertyDescriptor(source, key);
367
- let origDesc;
368
- if (descriptor.configurable === false) {
369
- descriptor.configurable = true;
370
- origDesc = {configurable: false};
371
- }
372
- if (descriptor.writable === false) {
373
- descriptor.writable = true;
374
- origDesc = {...origDesc, writable: false};
375
- }
376
- if (origDesc) {
377
- changedDescriptors.push([key, origDesc]);
378
- }
379
- Reflect.defineProperty(copy, key, descriptor);
380
- }
381
- if (changedDescriptors.length) {
382
- this._callbacks.push({
383
- func: restoreDescriptors,
384
- args: [copy, changedDescriptors],
385
- });
386
- }
387
- if (Object.isFrozen(source)) {
388
- this._callbacks.push({
389
- func: Object.freeze,
390
- args: [copy],
391
- });
392
- } else if (Object.isSealed(source)) {
393
- this._callbacks.push({
394
- func: Object.seal,
395
- args: [copy],
396
- });
397
- } else if (!Object.isExtensible(source)) {
398
- this._callbacks.push({
399
- func: Object.preventExtensions,
400
- args: [copy],
401
- });
402
- }
403
- return copy;
404
- }
405
-
406
- dangerouslySetAsMutable() {
407
- super.dangerouslySetAsMutable();
408
- this._callbacks = null;
409
- }
410
-
411
- revoke() {
412
- super.revoke();
413
- this._callbacks = null;
414
- }
415
-
416
- final() {
417
- const callbacks = this._callbacks;
418
- const result = super.final();
419
- if (callbacks) {
420
- for (let i = 0; i < callbacks.length; i++) {
421
- const {func, args} = callbacks[i];
422
- func(...args);
423
- }
424
- }
425
- return result;
426
- }
427
- }
428
-
429
- export default function mutate(source, strict = false) {
430
- if (strict) {
431
- return new CowContextStrict(source, null, null);
432
- } else {
433
- return new CowContext(source, null, null);
434
- }
369
+ export default function mutate(source) {
370
+ return new CowContext(source, null, null);
435
371
  }
package/src/index.js.flow CHANGED
@@ -1,106 +1,131 @@
1
1
  // @flow strict
2
2
 
3
- export type KeyType<+T> =
4
- T extends $ReadOnlyArray<mixed> ? number :
5
- T extends ({__proto__: null, ...} | interface {}) ? $Keys<T> :
3
+ export type KeyType<out T> =
4
+ T extends ReadonlyArray<unknown> ? number :
5
+ T extends ({__proto__: null, ...} | interface {}) ? keyof T :
6
6
  empty;
7
- export type KeyType2<+T, +K1: KeyType<T>> = KeyType<PropType<T, K1>>;
8
- export type KeyType3<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>> = KeyType<PropType2<T, K1, K2>>;
9
- export type KeyType4<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>> = KeyType<PropType3<T, K1, K2, K3>>;
10
- export type KeyType5<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>> = KeyType<PropType4<T, K1, K2, K3, K4>>;
11
- export type KeyType6<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>> = KeyType<PropType5<T, K1, K2, K3, K4, K5>>;
12
- export type KeyType7<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>, +K6: KeyType6<T, K1, K2, K3, K4, K5>> = KeyType<PropType6<T, K1, K2, K3, K4, K5, K6>>;
13
- export type KeyType8<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>, +K6: KeyType6<T, K1, K2, K3, K4, K5>, +K7: KeyType7<T, K1, K2, K3, K4, K5, K6>> = KeyType<PropType7<T, K1, K2, K3, K4, K5, K6, K7>>;
7
+ export type KeyType2<out T, out K1 extends KeyType<T>> = KeyType<PropType<T, K1>>;
8
+ export type KeyType3<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>> = KeyType<PropType2<T, K1, K2>>;
9
+ export type KeyType4<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>> = KeyType<PropType3<T, K1, K2, K3>>;
10
+ export type KeyType5<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>> = KeyType<PropType4<T, K1, K2, K3, K4>>;
11
+ export type KeyType6<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>> = KeyType<PropType5<T, K1, K2, K3, K4, K5>>;
12
+ export type KeyType7<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>, out K6 extends KeyType6<T, K1, K2, K3, K4, K5>> = KeyType<PropType6<T, K1, K2, K3, K4, K5, K6>>;
13
+ export type KeyType8<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>, out K6 extends KeyType6<T, K1, K2, K3, K4, K5>, out K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>> = KeyType<PropType7<T, K1, K2, K3, K4, K5, K6, K7>>;
14
14
 
15
- export type PropType<+T, +K: KeyType<T>> =
16
- T extends $ReadOnlyArray<infer V> ? V :
15
+ export type PropType<out T, out K extends KeyType<T>> =
16
+ T extends ReadonlyArray<infer V> ? V :
17
17
  T extends ({__proto__: null, ...} | interface {}) ? T[K] :
18
18
  empty;
19
- export type PropType2<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>> =
19
+ export type PropType2<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>> =
20
20
  PropType<PropType<T, K1>, K2>;
21
- export type PropType3<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>> =
21
+ export type PropType3<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>> =
22
22
  PropType<PropType2<T, K1, K2>, K3>;
23
- export type PropType4<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>> =
23
+ export type PropType4<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>> =
24
24
  PropType<PropType3<T, K1, K2, K3>, K4>;
25
- export type PropType5<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>> =
25
+ export type PropType5<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>> =
26
26
  PropType<PropType4<T, K1, K2, K3, K4>, K5>;
27
- export type PropType6<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>, +K6: KeyType6<T, K1, K2, K3, K4, K5>> =
27
+ export type PropType6<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>, out K6 extends KeyType6<T, K1, K2, K3, K4, K5>> =
28
28
  PropType<PropType5<T, K1, K2, K3, K4, K5>, K6>;
29
- export type PropType7<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>, +K6: KeyType6<T, K1, K2, K3, K4, K5>, +K7: KeyType7<T, K1, K2, K3, K4, K5, K6>> =
29
+ export type PropType7<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>, out K6 extends KeyType6<T, K1, K2, K3, K4, K5>, out K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>> =
30
30
  PropType<PropType6<T, K1, K2, K3, K4, K5, K6>, K7>;
31
- export type PropType8<+T, +K1: KeyType<T>, +K2: KeyType2<T, K1>, +K3: KeyType3<T, K1, K2>, +K4: KeyType4<T, K1, K2, K3>, +K5: KeyType5<T, K1, K2, K3, K4>, +K6: KeyType6<T, K1, K2, K3, K4, K5>, +K7: KeyType7<T, K1, K2, K3, K4, K5, K6>, +K8: KeyType8<T, K1, K2, K3, K4, K5, K6, K7>> =
31
+ export type PropType8<out T, out K1 extends KeyType<T>, out K2 extends KeyType2<T, K1>, out K3 extends KeyType3<T, K1, K2>, out K4 extends KeyType4<T, K1, K2, K3>, out K5 extends KeyType5<T, K1, K2, K3, K4>, out K6 extends KeyType6<T, K1, K2, K3, K4, K5>, out K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>, out K8 extends KeyType8<T, K1, K2, K3, K4, K5, K6, K7>> =
32
32
  PropType<PropType7<T, K1, K2, K3, K4, K5, K6, K7>, K8>;
33
33
 
34
- export type ShallowReadWrite<+T> =
35
- T extends $ReadOnlyArray<infer V> ? Array<V> :
34
+ export type NonMergeableObject =
35
+ | ReadonlyArray<unknown>
36
+ | ((...args: ReadonlyArray<empty>) => unknown)
37
+ | Date
38
+ | RegExp
39
+ | Error
40
+ | Promise<unknown>
41
+ | ReadonlyMap<unknown, unknown>
42
+ | ReadonlySet<unknown>
43
+ | $ReadOnlyWeakMap<interface {}, unknown>
44
+ | $ReadOnlyWeakSet<interface {}>
45
+ | ArrayBuffer
46
+ | $ArrayBufferView;
47
+
48
+ export type MergeValue<out V> =
49
+ V extends NonMergeableObject ? V :
50
+ V extends ({__proto__: null, ...} | interface {}) ? (V | MergeObject<V>) :
51
+ V;
52
+
53
+ export type MergeObject<out T> =
54
+ T extends NonMergeableObject ? empty :
55
+ T extends ({__proto__: null, ...} | interface {}) ? {readonly [K in keyof T]?: MergeValue<T[K]>} :
56
+ empty;
57
+
58
+ export type ShallowReadWrite<out T> =
59
+ T extends ReadonlyArray<infer V> ? Array<V> :
36
60
  T extends {__proto__: null, ...} ? {__proto__: null, ...T} :
37
61
  T extends {...} ? {...T} :
38
62
  T;
39
63
 
40
- export type CowRootContext<+R> = CowContext<R, null>;
64
+ export type CowRootContext<R> = CowContext<R, null>;
41
65
 
42
- export type CowAnyContext = CowContext<mixed, CowAnyContext | null>;
66
+ export type CowAnyContext = CowContext<unknown, CowAnyContext | null>;
43
67
 
44
- type $Get1<+T, +K1, +ThisContext> =
68
+ type $Get1<T, K1, out ThisContext> =
45
69
  CowContext<PropType<T, K1>, ThisContext>;
46
- type $Get2<+T, +K1, +K2, +ThisContext> =
70
+ type $Get2<T, K1, K2, out ThisContext> =
47
71
  CowContext<PropType2<T, K1, K2>, $Get1<T, K1, ThisContext>>;
48
- type $Get3<+T, +K1, +K2, +K3, +ThisContext> =
72
+ type $Get3<T, K1, K2, K3, out ThisContext> =
49
73
  CowContext<PropType3<T, K1, K2, K3>, $Get2<T, K1, K2, ThisContext>>;
50
- type $Get4<+T, +K1, +K2, +K3, +K4, +ThisContext> =
74
+ type $Get4<T, K1, K2, K3, K4, out ThisContext> =
51
75
  CowContext<PropType4<T, K1, K2, K3, K4>, $Get3<T, K1, K2, K3, ThisContext>>;
52
- type $Get5<+T, +K1, +K2, +K3, +K4, +K5, +ThisContext> =
76
+ type $Get5<T, K1, K2, K3, K4, K5, out ThisContext> =
53
77
  CowContext<PropType5<T, K1, K2, K3, K4, K5>, $Get4<T, K1, K2, K3, K4, ThisContext>>;
54
- type $Get6<+T, +K1, +K2, +K3, +K4, +K5, +K6, +ThisContext> =
78
+ type $Get6<T, K1, K2, K3, K4, K5, K6, out ThisContext> =
55
79
  CowContext<PropType6<T, K1, K2, K3, K4, K5, K6>, $Get5<T, K1, K2, K3, K4, K5, ThisContext>>;
56
- type $Get7<+T, +K1, +K2, +K3, +K4, +K5, +K6, +K7, +ThisContext> =
80
+ type $Get7<T, K1, K2, K3, K4, K5, K6, K7, out ThisContext> =
57
81
  CowContext<PropType7<T, K1, K2, K3, K4, K5, K6, K7>, $Get6<T, K1, K2, K3, K4, K5, K6, ThisContext>>;
58
- type $Get8<+T, +K1, +K2, +K3, +K4, +K5, +K6, +K7, +K8, +ThisContext> =
82
+ type $Get8<T, K1, K2, K3, K4, K5, K6, K7, K8, out ThisContext> =
59
83
  CowContext<PropType8<T, K1, K2, K3, K4, K5, K6, K7, K8>, $Get7<T, K1, K2, K3, K4, K5, K6, K7, ThisContext>>;
60
84
 
61
- export type GetCowContextSource<+C> =
62
- C extends CowContext<infer T, mixed>
85
+ export type GetCowContextSource<out C> =
86
+ C extends CowContext<infer T, unknown>
63
87
  ? T
64
88
  : empty;
65
89
 
66
- export type GetCowContextRoot<+C> =
90
+ export type GetCowContextRoot<out C> =
67
91
  C extends CowContext<infer T, infer P>
68
92
  ? (P extends null ? C : GetCowContextRoot<P>)
69
93
  : empty;
70
94
 
71
95
  declare export class CowContext<
72
- +T,
73
- +ParentContext: CowAnyContext | null = CowAnyContext | null,
96
+ T,
97
+ out ParentContext = CowAnyContext | null,
74
98
  >{
75
99
  read(): T;
76
100
  write(): ShallowReadWrite<T>;
77
101
  get(): this;
78
- get<const K1: KeyType<T>>(prop1: K1): $Get1<T, K1, this>;
79
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>>(prop1: K1, prop2: K2): $Get2<T, K1, K2, this>;
80
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>>(prop1: K1, prop2: K2, prop3: K3): $Get3<T, K1, K2, K3, this>;
81
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4): $Get4<T, K1, K2, K3, K4, this>;
82
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5): $Get5<T, K1, K2, K3, K4, K5, this>;
83
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6): $Get6<T, K1, K2, K3, K4, K5, K6, this>;
84
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>, const K7: KeyType7<T, K1, K2, K3, K4, K5, K6>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7): $Get7<T, K1, K2, K3, K4, K5, K6, K7, this>;
85
- get<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>, const K7: KeyType7<T, K1, K2, K3, K4, K5, K6>, const K8: KeyType8<T, K1, K2, K3, K4, K5, K6, K7>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, prop8: K8): $Get8<T, K1, K2, K3, K4, K5, K6, K7, K8, this>;
102
+ get<const K1 extends KeyType<T>>(prop1: K1): $Get1<T, K1, this>;
103
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>>(prop1: K1, prop2: K2): $Get2<T, K1, K2, this>;
104
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>>(prop1: K1, prop2: K2, prop3: K3): $Get3<T, K1, K2, K3, this>;
105
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4): $Get4<T, K1, K2, K3, K4, this>;
106
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5): $Get5<T, K1, K2, K3, K4, K5, this>;
107
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6): $Get6<T, K1, K2, K3, K4, K5, K6, this>;
108
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>, const K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7): $Get7<T, K1, K2, K3, K4, K5, K6, K7, this>;
109
+ get<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>, const K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>, const K8 extends KeyType8<T, K1, K2, K3, K4, K5, K6, K7>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, prop8: K8): $Get8<T, K1, K2, K3, K4, K5, K6, K7, K8, this>;
86
110
  set(newValue: T): this;
87
- set<const K1: KeyType<T>>(prop1: K1, newValue: PropType<T, K1>): this;
88
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>>(prop1: K1, prop2: K2, newValue: PropType2<T, K1, K2>): this;
89
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>>(prop1: K1, prop2: K2, prop3: K3, newValue: PropType3<T, K1, K2, K3>): this;
90
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, newValue: PropType4<T, K1, K2, K3, K4>): this;
91
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, newValue: PropType5<T, K1, K2, K3, K4, K5>): this;
92
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, newValue: PropType6<T, K1, K2, K3, K4, K5, K6>): this;
93
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>, const K7: KeyType7<T, K1, K2, K3, K4, K5, K6>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, newValue: PropType7<T, K1, K2, K3, K4, K5, K6, K7>): this;
94
- set<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>, const K7: KeyType7<T, K1, K2, K3, K4, K5, K6>, const K8: KeyType8<T, K1, K2, K3, K4, K5, K6, K7>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, prop8: K8, newValue: PropType8<T, K1, K2, K3, K4, K5, K6, K7, K8>): this;
95
- update(updater: (this) => mixed): this;
96
- update<const K1: KeyType<T>>(prop1: K1, updater: ($Get1<T, K1, this>) => mixed): this;
97
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>>(prop1: K1, prop2: K2, updater: ($Get2<T, K1, K2, this>) => mixed): this;
98
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>>(prop1: K1, prop2: K2, prop3: K3, updater: ($Get3<T, K1, K2, K3, this>) => mixed): this;
99
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, updater: ($Get4<T, K1, K2, K3, K4, this>) => mixed): this;
100
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, updater: ($Get5<T, K1, K2, K3, K4, K5, this>) => mixed): this;
101
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, updater: ($Get6<T, K1, K2, K3, K4, K5, K6, this>) => mixed): this;
102
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>, const K7: KeyType7<T, K1, K2, K3, K4, K5, K6>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, updater: ($Get7<T, K1, K2, K3, K4, K5, K6, K7, this>) => mixed): this;
103
- update<const K1: KeyType<T>, const K2: KeyType2<T, K1>, const K3: KeyType3<T, K1, K2>, const K4: KeyType4<T, K1, K2, K3>, const K5: KeyType5<T, K1, K2, K3, K4>, const K6: KeyType6<T, K1, K2, K3, K4, K5>, const K7: KeyType7<T, K1, K2, K3, K4, K5, K6>, const K8: KeyType8<T, K1, K2, K3, K4, K5, K6, K7>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, prop8: K8, updater: ($Get8<T, K1, K2, K3, K4, K5, K6, K7, K8, this>) => mixed): this;
111
+ set<const K1 extends KeyType<T>>(prop1: K1, newValue: PropType<T, K1>): this;
112
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>>(prop1: K1, prop2: K2, newValue: PropType2<T, K1, K2>): this;
113
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>>(prop1: K1, prop2: K2, prop3: K3, newValue: PropType3<T, K1, K2, K3>): this;
114
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, newValue: PropType4<T, K1, K2, K3, K4>): this;
115
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, newValue: PropType5<T, K1, K2, K3, K4, K5>): this;
116
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, newValue: PropType6<T, K1, K2, K3, K4, K5, K6>): this;
117
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>, const K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, newValue: PropType7<T, K1, K2, K3, K4, K5, K6, K7>): this;
118
+ set<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>, const K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>, const K8 extends KeyType8<T, K1, K2, K3, K4, K5, K6, K7>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, prop8: K8, newValue: PropType8<T, K1, K2, K3, K4, K5, K6, K7, K8>): this;
119
+ merge(object: MergeObject<T>): this;
120
+ update(updater: (this) => unknown): this;
121
+ update<const K1 extends KeyType<T>>(prop1: K1, updater: ($Get1<T, K1, this>) => unknown): this;
122
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>>(prop1: K1, prop2: K2, updater: ($Get2<T, K1, K2, this>) => unknown): this;
123
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>>(prop1: K1, prop2: K2, prop3: K3, updater: ($Get3<T, K1, K2, K3, this>) => unknown): this;
124
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, updater: ($Get4<T, K1, K2, K3, K4, this>) => unknown): this;
125
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, updater: ($Get5<T, K1, K2, K3, K4, K5, this>) => unknown): this;
126
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, updater: ($Get6<T, K1, K2, K3, K4, K5, K6, this>) => unknown): this;
127
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>, const K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, updater: ($Get7<T, K1, K2, K3, K4, K5, K6, K7, this>) => unknown): this;
128
+ update<const K1 extends KeyType<T>, const K2 extends KeyType2<T, K1>, const K3 extends KeyType3<T, K1, K2>, const K4 extends KeyType4<T, K1, K2, K3>, const K5 extends KeyType5<T, K1, K2, K3, K4>, const K6 extends KeyType6<T, K1, K2, K3, K4, K5>, const K7 extends KeyType7<T, K1, K2, K3, K4, K5, K6>, const K8 extends KeyType8<T, K1, K2, K3, K4, K5, K6, K7>>(prop1: K1, prop2: K2, prop3: K3, prop4: K4, prop5: K5, prop6: K6, prop7: K7, prop8: K8, updater: ($Get8<T, K1, K2, K3, K4, K5, K6, K7, K8, this>) => unknown): this;
104
129
  dangerouslySetAsMutable(): void;
105
130
  parent(): ParentContext;
106
131
  root(): GetCowContextRoot<this>;
@@ -112,5 +137,4 @@ declare export class CowContext<
112
137
 
113
138
  declare export default function mutate<T>(
114
139
  source: T,
115
- strict?: boolean,
116
140
  ): CowRootContext<T>;
package/types/index.d.ts CHANGED
@@ -1,24 +1,55 @@
1
+ type KeyOf<T> =
2
+ T extends ReadonlyArray<unknown> ? number : keyof T;
3
+
4
+ type PropOf<T, K> =
5
+ T extends ReadonlyArray<infer V> ? V :
6
+ K extends keyof T ? T[K] : never;
7
+
1
8
  type NestedProp<T, Path extends ReadonlyArray<PropertyKey>> =
2
9
  Path extends [infer First, ...infer Rest]
3
10
  ? (
4
- First extends keyof T
5
- ? NestedProp<T[First], Extract<Rest, ReadonlyArray<PropertyKey>>>
11
+ First extends KeyOf<T>
12
+ ? NestedProp<PropOf<T, First>, Extract<Rest, ReadonlyArray<PropertyKey>>>
6
13
  : never
7
14
  )
8
15
  : T;
9
16
 
10
- type NestedContext<T, ParentContext extends CowAnyContext | null, Path extends ReadonlyArray<PropertyKey>> =
17
+ type NestedContext<T, ParentContext, Path extends ReadonlyArray<PropertyKey>> =
11
18
  Path extends [infer First, ...infer Rest]
12
19
  ? (
13
- First extends keyof T
14
- ? NestedContext<T[First], CowContext<T, ParentContext>, Extract<Rest, ReadonlyArray<PropertyKey>>>
20
+ First extends KeyOf<T>
21
+ ? NestedContext<PropOf<T, First>, CowContext<T, ParentContext>, Extract<Rest, ReadonlyArray<PropertyKey>>>
15
22
  : never
16
23
  )
17
24
  : CowContext<T, ParentContext>;
18
25
 
26
+ type NonMergeableObject =
27
+ | ReadonlyArray<unknown>
28
+ | ((...args: never[]) => unknown)
29
+ | Date
30
+ | RegExp
31
+ | Error
32
+ | Promise<unknown>
33
+ | ReadonlyMap<unknown, unknown>
34
+ | ReadonlySet<unknown>
35
+ | WeakMap<object, unknown>
36
+ | WeakSet<object>
37
+ | ArrayBuffer
38
+ | ArrayBufferView;
39
+
40
+ type MergeValue<V> =
41
+ V extends NonMergeableObject ? V :
42
+ V extends object ? V | MergeObject<V> :
43
+ V;
44
+
45
+ type MergeObject<T> =
46
+ T extends NonMergeableObject ? never :
47
+ T extends object ? {[K in keyof T]?: MergeValue<T[K]>} :
48
+ never;
49
+
19
50
  type ShallowReadWrite<T> =
20
51
  T extends ReadonlyArray<infer V> ? Array<V> :
21
- T extends object ? {-readonly [K in keyof T]: T[K]} : never;
52
+ T extends object ? {-readonly [K in keyof T]: T[K]} : T;
22
53
 
23
54
  type CowRootContext<R> = CowContext<R, null>;
24
55
 
@@ -37,13 +68,13 @@ type GetCowContextRoot<C> =
37
68
 
38
69
  declare class CowContext<
39
70
  out T,
40
- // @ts-ignore
41
- out ParentContext extends CowAnyContext | null = CowAnyContext | null,
71
+ out ParentContext = CowAnyContext | null,
42
72
  > {
43
73
  read(): T;
44
74
  write(): ShallowReadWrite<T>;
45
75
  get<Path extends ReadonlyArray<PropertyKey>>(...path: Path): NestedContext<T, ParentContext, Path>;
46
76
  set<Path extends ReadonlyArray<PropertyKey>>(...args: [...Path, NestedProp<T, Path>]): this;
77
+ merge(object: MergeObject<T>): this;
47
78
  update<Path extends ReadonlyArray<PropertyKey>>(...args: [...Path, (childContext: NestedContext<T, ParentContext, Path>) => unknown]): this;
48
79
  dangerouslySetAsMutable(): void;
49
80
  parent(): ParentContext;
@@ -56,7 +87,6 @@ declare class CowContext<
56
87
 
57
88
  declare function mutate<T>(
58
89
  source: T,
59
- strict?: boolean,
60
90
  ): CowRootContext<T>;
61
91
 
62
92
  export {CowRootContext, CowAnyContext, CowContext};