mutate-cow 8.0.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.0.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.275.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
@@ -5,190 +5,110 @@
5
5
  * in the file named "LICENSE" at the root directory of this distribution.
6
6
  */
7
7
 
8
+ const EMPTY_OBJECT = Object.freeze({});
9
+
8
10
  const NATIVE_CODE_REGEXP = /^function \w*\(\) \{\s*\[native code\]\s*\}$/m;
9
11
 
12
+ const TYPE_PRIMITIVE = 1;
13
+ const TYPE_PLAIN_OBJECT = 2;
14
+ const TYPE_PLAIN_ARRAY = 3;
15
+ const TYPE_UNSUPPORTED = 4;
16
+
10
17
  const STATUS_NONE = 1;
11
18
  const STATUS_MUTABLE = 2;
12
19
  const STATUS_REVOKED = 3;
13
20
  const STATUS_STALE = 4;
14
21
 
15
- function isPrimitive(value) {
22
+ function getValueType(value) {
16
23
  if (value === null) {
17
- return true;
24
+ return TYPE_PRIMITIVE;
18
25
  }
19
26
  const type = typeof value;
20
- return (type !== 'function' && type !== 'object');
21
- }
22
-
23
- function isCloneableObject(object) {
24
- if (typeof object === 'function') {
25
- return false;
26
- }
27
- let proto = Object.getPrototypeOf(object);
28
- while (proto) {
29
- let ctor = proto.constructor;
30
- if (!ctor) {
31
- continue;
32
- }
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
- proto = Object.getPrototypeOf(proto);
46
- }
47
- return true;
48
- }
49
-
50
- function printConstructor(object) {
51
- const ctor = object.constructor;
52
- switch (typeof ctor) {
53
- case 'function':
54
- return ctor.name;
55
- case 'object':
56
- return Object.prototype.toString.call(ctor);
57
- default:
58
- return '';
59
- }
60
- }
61
-
62
- function restoreDescriptors(copy, changedDescriptors) {
63
- for (let i = 0; i < changedDescriptors.length; i++) {
64
- const [name, origDesc] = changedDescriptors[i];
65
- const descriptor = Object.getOwnPropertyDescriptor(copy, name);
66
- if (descriptor) {
67
- Object.assign(descriptor, origDesc);
68
- Reflect.defineProperty(copy, name, descriptor);
69
- }
70
- }
71
- }
72
-
73
- function clone(context) {
74
- const source = context._getSource();
75
- if (isPrimitive(source)) {
76
- return source;
77
- }
78
- if (!isCloneableObject(source)) {
79
- throw new Error(
80
- printConstructor(source) +
81
- ' objects are not supported for cloning.',
82
- );
83
- }
84
- if (context._strict) {
85
- return cloneObjectStrict(source, context);
86
- }
87
- return cloneObjectLoose(source);
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;
88
46
  }
89
47
 
90
- function cloneObjectLoose(source) {
91
- if (Array.isArray(source)) {
92
- return source.slice();
93
- }
94
- return {...source};
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
+ );
95
56
  }
96
57
 
97
- function cloneObjectStrict(source, context) {
98
- if (!context._callbacks) {
99
- context._callbacks = [];
100
- }
101
- const proto = Object.getPrototypeOf(source);
102
- let changedDescriptors = [];
103
- let copy;
104
- if (Array.isArray(source)) {
105
- copy = Reflect.construct(Array, source, proto.constructor);
106
- } else {
107
- copy = Object.create(proto);
108
- }
109
- const ownKeys = Reflect.ownKeys(source);
110
- for (let i = 0; i < ownKeys.length; i++) {
111
- const key = ownKeys[i];
112
- const descriptor = Object.getOwnPropertyDescriptor(source, key);
113
- let origDesc;
114
- if (descriptor.configurable === false) {
115
- descriptor.configurable = true;
116
- origDesc = {configurable: false};
117
- }
118
- if (descriptor.writable === false) {
119
- descriptor.writable = true;
120
- origDesc = {...origDesc, writable: false};
121
- }
122
- if (origDesc) {
123
- changedDescriptors.push([key, origDesc]);
124
- }
125
- Reflect.defineProperty(copy, key, descriptor);
126
- }
127
- if (changedDescriptors.length) {
128
- context._callbacks.push({
129
- func: restoreDescriptors,
130
- args: [copy, changedDescriptors],
131
- });
132
- }
133
- if (Object.isFrozen(source)) {
134
- context._callbacks.push({
135
- func: Object.freeze,
136
- args: [copy],
137
- });
138
- } else if (Object.isSealed(source)) {
139
- context._callbacks.push({
140
- func: Object.seal,
141
- args: [copy],
142
- });
143
- } else if (!Object.isExtensible(source)) {
144
- context._callbacks.push({
145
- func: Object.preventExtensions,
146
- args: [copy],
147
- });
148
- }
149
- return copy;
58
+ function setProtoProperty(object, value) {
59
+ Reflect.defineProperty(object, '__proto__', {
60
+ value,
61
+ writable: true,
62
+ enumerable: true,
63
+ configurable: true,
64
+ });
150
65
  }
151
66
 
152
67
  export class CowContext {
153
- constructor(source, prop, parent, strict = false) {
68
+ constructor(source, prop, parent) {
154
69
  this._source = source;
155
70
  this._prop = prop;
156
71
  this._parent = parent;
157
- this._callbacks = null;
158
72
  this._result = null;
159
73
  this._status = STATUS_NONE;
160
74
  this._children = null;
161
- this._strict = strict;
162
75
  }
163
76
 
164
- _copyForWrite() {
165
- const status = this._status;
166
- if (
167
- status === STATUS_MUTABLE ||
168
- status === STATUS_REVOKED
169
- ) {
77
+ _copyForWrite(forceObject) {
78
+ if (this._status === STATUS_MUTABLE || this._status === STATUS_REVOKED) {
170
79
  return;
171
80
  }
172
- const stack = [];
173
- let parent = this;
174
- while (parent && parent._status !== STATUS_MUTABLE) {
175
- stack.push(parent);
176
- parent = parent._parent;
177
- }
178
- for (let i = stack.length - 1; i >= 0; i--) {
179
- const context = stack[i];
180
- if (!context._result) {
181
- context._result = clone(context);
81
+ if (!this._result) {
82
+ const source = this._getSource();
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.');
182
95
  }
183
- if (context._parent) {
184
- context._parent._result[context._prop] = context._result;
96
+ }
97
+ const parent = this._parent;
98
+ if (parent) {
99
+ parent._copyForWrite(/* forceObject = */ true);
100
+ const prop = this._prop;
101
+ if (prop === '__proto__') {
102
+ setProtoProperty(parent._result, this._result);
103
+ } else {
104
+ parent._result[prop] = this._result;
185
105
  }
186
- context._status = STATUS_MUTABLE;
187
106
  }
107
+ this._status = STATUS_MUTABLE;
188
108
  }
189
109
 
190
110
  _getPropValue(prop) {
191
- return Reflect.get(this._read(), prop);
111
+ return Reflect.get(this._read() ?? EMPTY_OBJECT, prop);
192
112
  }
193
113
 
194
114
  _getSource() {
@@ -222,7 +142,7 @@ export class CowContext {
222
142
 
223
143
  write() {
224
144
  this._throwIfRevoked();
225
- this._copyForWrite();
145
+ this._copyForWrite(/* forceObject = */ false);
226
146
  return this._result;
227
147
  }
228
148
 
@@ -240,7 +160,7 @@ export class CowContext {
240
160
  return child;
241
161
  }
242
162
 
243
- child = new CowContext(value, prop, this, this._strict);
163
+ child = new this.constructor(value, prop, this);
244
164
  children.set(prop, child);
245
165
  return child;
246
166
  }
@@ -261,7 +181,6 @@ export class CowContext {
261
181
  } else {
262
182
  this._source = value;
263
183
  this._status = STATUS_NONE;
264
- this._callbacks = null;
265
184
  this._result = null;
266
185
  // Child source values must be invalidated, because they can
267
186
  // reference a previous copy we made.
@@ -270,8 +189,12 @@ export class CowContext {
270
189
  }
271
190
 
272
191
  _set(prop, newValue) {
273
- this._copyForWrite();
274
- this._result[prop] = newValue;
192
+ this._copyForWrite(/* forceObject = */ true);
193
+ if (prop === '__proto__') {
194
+ setProtoProperty(this._result, newValue);
195
+ } else {
196
+ this._result[prop] = newValue;
197
+ }
275
198
 
276
199
  // Child source values must be invalidated, because they can
277
200
  // reference a previous copy we made.
@@ -285,9 +208,10 @@ export class CowContext {
285
208
  }
286
209
 
287
210
  _setIfChanged(prop, newValue) {
211
+ const object = this._read() ?? EMPTY_OBJECT;
288
212
  if (
289
- !Object.hasOwn(this._read(), prop) ||
290
- !Object.is(this._getPropValue(prop), newValue)
213
+ !Object.hasOwn(object, prop) ||
214
+ !Object.is(Reflect.get(object, prop), newValue)
291
215
  ) {
292
216
  this._set(prop, newValue);
293
217
  }
@@ -295,7 +219,6 @@ export class CowContext {
295
219
 
296
220
  _setStale() {
297
221
  this._source = null;
298
- this._callbacks = null;
299
222
  this._result = null;
300
223
  this._status = STATUS_STALE;
301
224
  this._setAllChildrenAsStale();
@@ -323,6 +246,44 @@ export class CowContext {
323
246
  return this;
324
247
  }
325
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
+
326
287
  update(...args) {
327
288
  const updater = args.pop();
328
289
  updater(this.get(...args));
@@ -341,7 +302,6 @@ export class CowContext {
341
302
  this._source = source;
342
303
  this._result = mutableValue;
343
304
  this._status = STATUS_MUTABLE;
344
- this._callbacks = null;
345
305
  this._setAllChildrenAsStale();
346
306
  }
347
307
 
@@ -359,27 +319,31 @@ export class CowContext {
359
319
  return root;
360
320
  }
361
321
 
362
- revoke() {
322
+ _revoke(recursive) {
363
323
  if (this.isRevoked()) {
364
324
  return;
365
325
  }
366
326
  if (this._parent) {
367
327
  this._parent._children.delete(this._prop);
368
328
  }
369
- if (this._children) {
370
- for (const child of this._children.values()) {
371
- child.revoke();
329
+ if (recursive && this._children) {
330
+ const childrenToRevoke = [...this._children.values()];
331
+ for (const child of childrenToRevoke) {
332
+ child._revoke(true);
372
333
  }
373
- this._children = null;
374
334
  }
335
+ this._children = null;
375
336
  this._source = null;
376
337
  this._prop = null;
377
338
  this._parent = null;
378
- this._callbacks = null;
379
339
  this._result = null;
380
340
  this._status = STATUS_REVOKED;
381
341
  }
382
342
 
343
+ revoke() {
344
+ this._revoke(/* recursive = */ true);
345
+ }
346
+
383
347
  isRevoked() {
384
348
  return this._status === STATUS_REVOKED;
385
349
  }
@@ -387,19 +351,13 @@ export class CowContext {
387
351
  final() {
388
352
  this._throwIfRevoked();
389
353
  if (this._children) {
390
- for (const child of this._children.values()) {
354
+ const childrenToFinalize = [...this._children.values()];
355
+ for (const child of childrenToFinalize) {
391
356
  child.final();
392
357
  }
393
358
  }
394
359
  const result = this._read();
395
- const callbacks = this._callbacks;
396
- this.revoke();
397
- if (callbacks) {
398
- for (let i = 0; i < callbacks.length; i++) {
399
- const {func, args} = callbacks[i];
400
- func(...args);
401
- }
402
- }
360
+ this._revoke(/* recursive = */ false);
403
361
  return result;
404
362
  }
405
363
 
@@ -408,6 +366,6 @@ export class CowContext {
408
366
  }
409
367
  }
410
368
 
411
- export default function mutate(source, strict = false) {
412
- return new CowContext(source, null, null, strict);
369
+ export default function mutate(source) {
370
+ return new CowContext(source, null, null);
413
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};