mobx-keystone 2.2.0 → 2.3.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.
@@ -1,5 +1,14 @@
1
+ import { modelTypeKey } from "../../model/metadata"
2
+ import { getModelInfoForName } from "../../modelShared/modelInfo"
1
3
  import { failure, lazy } from "../../utils"
2
4
  import { getTypeInfo } from "../getTypeInfo"
5
+ import {
6
+ findClosestModelTypeMatch,
7
+ findFirstMatch,
8
+ getModelTypeMatchingPass,
9
+ hasSnapshotModelType,
10
+ matchUnlessModelSnapshotRejected,
11
+ } from "../modelTypeMatching"
3
12
  import {
4
13
  resolveStandardType,
5
14
  resolveStandardTypeNoThrow,
@@ -195,17 +204,34 @@ export function typesOr(
195
204
  // this is done because:
196
205
  // 1) performance (avoid checking structure if not needed)
197
206
  // 2) so we can accept untyped models when paired with undefined | null
198
- return checkerForBaseType[0]
199
- }
200
-
201
- for (let i = 0; i < checkerForBaseType.length; i++) {
202
- const matchingType = checkerForBaseType[i].snapshotType(value)
203
- if (matchingType) {
204
- return matchingType
207
+ const candidate = checkerForBaseType[0]
208
+ if (
209
+ getModelTypeMatchingPass() !== "none" &&
210
+ valueBaseType !== TypeCheckerBaseType.Primitive
211
+ ) {
212
+ // an outer union is matching its branches, so let it know whether this one matches
213
+ // the (possibly nested) snapshot models; if it does not because a (possibly nested)
214
+ // model type rejected a model snapshot (in the exact pass, also one of a subclass),
215
+ // or because the snapshot names a registered model this branch does not accept, the
216
+ // outer union has to try other branches first, else it might pick a farther branch
217
+ // or one that rejects the snapshot
218
+ const matched = matchUnlessModelSnapshotRejected(matchSnapshotType, candidate, value)
219
+ if (
220
+ matched === undefined ||
221
+ (!matched &&
222
+ hasSnapshotModelType(value) &&
223
+ getModelInfoForName((value as any)[modelTypeKey]))
224
+ ) {
225
+ return null
226
+ }
205
227
  }
228
+ return candidate
206
229
  }
207
230
 
208
- return null
231
+ // prefer branches whose (possibly nested) models are the closest to the snapshot ones
232
+ return valueBaseType === TypeCheckerBaseType.Primitive
233
+ ? (findFirstMatch(checkerForBaseType, matchSnapshotType, value) ?? null)
234
+ : (findClosestModelTypeMatch(checkerForBaseType, matchSnapshotType, value) ?? null)
209
235
  },
210
236
 
211
237
  snapshotProcessorPlan(
@@ -272,3 +298,7 @@ export class OrTypeInfo extends TypeInfo {
272
298
  this.dispatcher = dispatcher
273
299
  }
274
300
  }
301
+
302
+ function matchSnapshotType(checker: TypeChecker, value: unknown): TypeChecker | null {
303
+ return checker.snapshotType(value)
304
+ }