@jbrowse/mobx-state-tree 6.2.0 → 6.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.
@@ -480,30 +480,20 @@ function getIdentifier(target) {
480
480
  return getStateTreeNode(target).identifier;
481
481
  }
482
482
  /**
483
- * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns such reference if the check passes,
484
- * else it returns undefined.
485
- *
486
- * @param getter Function to access the reference.
487
- * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
488
- * @returns
483
+ * Resolves a reference getter to the referenced node, or `undefined` when the
484
+ * reference is empty, dangling, or (with `checkIfAlive`) points at a dead node.
485
+ * Backs both {@link tryReference} and {@link isValidReference}.
489
486
  */
490
- function tryReference(getter, checkIfAlive = true) {
487
+ function resolveReference(getter, checkIfAlive) {
491
488
  try {
492
489
  const node = getter();
493
490
  if (node === undefined || node === null) {
494
491
  return undefined;
495
492
  }
496
- else if (isStateTreeNode(node)) {
497
- if (!checkIfAlive) {
498
- return node;
499
- }
500
- else {
501
- return isAlive(node) ? node : undefined;
502
- }
503
- }
504
- else {
493
+ if (!isStateTreeNode(node)) {
505
494
  throw fail("The reference to be checked is not one of node, null or undefined");
506
495
  }
496
+ return !checkIfAlive || isAlive(node) ? node : undefined;
507
497
  }
508
498
  catch (e) {
509
499
  if (e instanceof InvalidReferenceError) {
@@ -512,6 +502,17 @@ function tryReference(getter, checkIfAlive = true) {
512
502
  throw e;
513
503
  }
514
504
  }
505
+ /**
506
+ * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns such reference if the check passes,
507
+ * else it returns undefined.
508
+ *
509
+ * @param getter Function to access the reference.
510
+ * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
511
+ * @returns
512
+ */
513
+ function tryReference(getter, checkIfAlive = true) {
514
+ return resolveReference(getter, checkIfAlive);
515
+ }
515
516
  /**
516
517
  * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns if the check passes or not.
517
518
  *
@@ -520,24 +521,7 @@ function tryReference(getter, checkIfAlive = true) {
520
521
  * @returns
521
522
  */
522
523
  function isValidReference(getter, checkIfAlive = true) {
523
- try {
524
- const node = getter();
525
- if (node === undefined || node === null) {
526
- return false;
527
- }
528
- else if (isStateTreeNode(node)) {
529
- return checkIfAlive ? isAlive(node) : true;
530
- }
531
- else {
532
- throw fail("The reference to be checked is not one of node, null or undefined");
533
- }
534
- }
535
- catch (e) {
536
- if (e instanceof InvalidReferenceError) {
537
- return false;
538
- }
539
- throw e;
540
- }
524
+ return resolveReference(getter, checkIfAlive) !== undefined;
541
525
  }
542
526
  /**
543
527
  * Try to resolve a given path relative to a given node.
@@ -1959,7 +1943,6 @@ function assertIsType(type, argNumber) {
1959
1943
  assertArg(type, isType, "mobx-state-tree type", argNumber);
1960
1944
  }
1961
1945
 
1962
- const runningActions = new Map();
1963
1946
  /**
1964
1947
  * Note: Consider migrating to `createActionTrackingMiddleware2`, it is easier to use.
1965
1948
  *
@@ -1975,6 +1958,12 @@ const runningActions = new Map();
1975
1958
  * @returns
1976
1959
  */
1977
1960
  function createActionTrackingMiddleware(hooks) {
1961
+ // per middleware, not per module: the entries hold the `context` this
1962
+ // middleware's own onStart returned, so two middlewares on one tree would
1963
+ // otherwise overwrite each other's context and then delete the shared entry —
1964
+ // whichever saw `flow_return` second dereferenced `undefined`.
1965
+ // createActionTrackingMiddleware2 scopes its map the same way.
1966
+ const runningActions = new Map();
1978
1967
  return function actionTrackingMiddleware(call, next, _abort) {
1979
1968
  switch (call.type) {
1980
1969
  case "action": {
@@ -2697,6 +2686,8 @@ function shortenPrintValue(valueInString) {
2697
2686
  }
2698
2687
  function toErrorString(error) {
2699
2688
  const { value } = error;
2689
+ // every context entry carries a type: they are built by getContextForPath and
2690
+ // by typecheck's initial `[{ path: "", type }]`
2700
2691
  const type = error.context[error.context.length - 1].type;
2701
2692
  const fullPath = error.context
2702
2693
  .map(({ path }) => path)
@@ -2708,14 +2699,21 @@ function toErrorString(error) {
2708
2699
  : isPrimitive(value)
2709
2700
  ? "value"
2710
2701
  : "snapshot";
2711
- const isSnapshotCompatible = type && isStateTreeNode(value) && type.is(getStateTreeNode(value).snapshot);
2712
- return `${pathPrefix}${currentTypename} ${shortenPrintValue(prettyPrintValue(value))} is not assignable ${type ? `to type: \`${type.name}\`` : ``}${error.message ? ` (${error.message})` : ""}${type
2713
- ? isPrimitiveType(type) || isPrimitive(value)
2714
- ? `.`
2715
- : `, expected an instance of \`${type.name}\` or a snapshot like \`${shortenPrintValue(type.describe())}\` instead.${isSnapshotCompatible
2716
- ? " (Note that a snapshot of the provided value is compatible with the targeted type)"
2717
- : ""}`
2718
- : `.`}`;
2702
+ let expectation;
2703
+ if (isPrimitiveType(type) || isPrimitive(value)) {
2704
+ expectation = ".";
2705
+ }
2706
+ else {
2707
+ // `isPrimitiveType` is declared `(type: IT) => type is IT`, so its negative
2708
+ // branch narrows to `never` rather than to "some non-primitive type"; the
2709
+ // annotation restores the type it actually has here.
2710
+ const complexType = type;
2711
+ const isSnapshotCompatible = isStateTreeNode(value) && complexType.is(getStateTreeNode(value).snapshot);
2712
+ expectation = `, expected an instance of \`${complexType.name}\` or a snapshot like \`${shortenPrintValue(complexType.describe())}\` instead.${isSnapshotCompatible
2713
+ ? " (Note that a snapshot of the provided value is compatible with the targeted type)"
2714
+ : ""}`;
2715
+ }
2716
+ return `${pathPrefix}${currentTypename} ${shortenPrintValue(prettyPrintValue(value))} is not assignable to type: \`${type.name}\`${error.message ? ` (${error.message})` : ""}${expectation}`;
2719
2717
  }
2720
2718
  /**
2721
2719
  * @internal
@@ -3544,6 +3542,8 @@ function createFlowSpawner(name, generator) {
3544
3542
  const spawner = function flowSpawner(...flowArgs) {
3545
3543
  // Implementation based on https://github.com/tj/co/blob/master/index.js
3546
3544
  const runId = getNextActionId();
3545
+ // no `!`: the guard below is the point, and asserting non-null first made it
3546
+ // dead to the checker while leaving it live at runtime
3547
3547
  const parentContext = getCurrentActionContext();
3548
3548
  if (!parentContext) {
3549
3549
  throw fail("a mst flow must always have a parent context");
@@ -3812,8 +3812,10 @@ class SnapshotProcessor extends BaseType {
3812
3812
  return sn;
3813
3813
  }
3814
3814
  _fixNode(node) {
3815
- // the node has to use these methods rather than the original type ones
3816
- proxyNodeTypeMethods(node.type, this, "create");
3815
+ // the node's type is the *inner* type, so `getType(instance).create(...)`
3816
+ // would bypass the processors — point it at ours instead
3817
+ const nodeType = node.type;
3818
+ nodeType.create = this.create.bind(this);
3817
3819
  if (node instanceof ObjectNode) {
3818
3820
  node.hasSnapshotPostProcessor = !!this._processors.postProcessor;
3819
3821
  }
@@ -3882,11 +3884,6 @@ class SnapshotProcessor extends BaseType {
3882
3884
  return this._subtype.isMatchingSnapshotId(current, processedSn);
3883
3885
  }
3884
3886
  }
3885
- function proxyNodeTypeMethods(nodeType, snapshotProcessorType, ...methods) {
3886
- for (const method of methods) {
3887
- nodeType[method] = snapshotProcessorType[method].bind(snapshotProcessorType);
3888
- }
3889
- }
3890
3887
  /**
3891
3888
  * `types.snapshotProcessor` - Runs a pre/post snapshot processor before/after serializing a given type.
3892
3889
  *
@@ -3937,6 +3934,41 @@ function snapshotProcessor(type, processors, name) {
3937
3934
  return new SnapshotProcessor(type, processors, name);
3938
3935
  }
3939
3936
 
3937
+ /**
3938
+ * Append `hooks` to a collection type's initializer list. `EMPTY_ARRAY` is the
3939
+ * shared default, so a type that never calls `.hooks()` allocates nothing.
3940
+ *
3941
+ * @internal
3942
+ * @hidden
3943
+ */
3944
+ function appendHookInitializer(current, hooks) {
3945
+ return current.length > 0 ? [...current, hooks] : [hooks];
3946
+ }
3947
+ /**
3948
+ * Install every hook the type's initializers produce onto `instance` as an MST
3949
+ * action, mirroring how a model's `.actions()` members are attached.
3950
+ *
3951
+ * @internal
3952
+ * @hidden
3953
+ */
3954
+ function installHookInitializers(hookInitializers, instance) {
3955
+ const addProp = !devMode() ? addHiddenFinalProp : addHiddenWritableProp;
3956
+ for (const initializer of hookInitializers) {
3957
+ const hooks = initializer(instance);
3958
+ for (const name of Object.keys(hooks)) {
3959
+ const hook = hooks[name];
3960
+ addProp(instance, name, createActionInvoker(instance, name, hook));
3961
+ }
3962
+ }
3963
+ }
3964
+ /**
3965
+ * The empty initializer list every collection type starts with.
3966
+ *
3967
+ * @internal
3968
+ * @hidden
3969
+ */
3970
+ const NO_HOOK_INITIALIZERS = EMPTY_ARRAY;
3971
+
3940
3972
  const needsIdentifierError = `Map.put can only be used to store complex values that have an identifier type attribute`;
3941
3973
  function tryCollectModelTypes(type, modelTypes) {
3942
3974
  const subtypes = type.getSubTypes();
@@ -4033,24 +4065,21 @@ class MSTMap extends ObservableMap {
4033
4065
  */
4034
4066
  class MapType extends ComplexType {
4035
4067
  _subType;
4068
+ hookInitializers;
4036
4069
  identifierMode = MapIdentifierMode.UNKNOWN;
4037
4070
  mapIdentifierAttribute = undefined;
4038
4071
  flags = TypeFlags.Map;
4039
- hookInitializers = [];
4040
- constructor(_subType, hookInitializers = []) {
4072
+ constructor(_subType, hookInitializers = NO_HOOK_INITIALIZERS) {
4041
4073
  super();
4042
4074
  this._subType = _subType;
4043
- this._determineIdentifierMode();
4044
4075
  this.hookInitializers = hookInitializers;
4076
+ this._determineIdentifierMode();
4045
4077
  }
4046
4078
  computeName() {
4047
4079
  return `Map<string, ${this._subType.name}>`;
4048
4080
  }
4049
4081
  hooks(hooks) {
4050
- const hookInitializers = this.hookInitializers.length > 0
4051
- ? this.hookInitializers.concat(hooks)
4052
- : [hooks];
4053
- return new MapType(this._subType, hookInitializers);
4082
+ return new MapType(this._subType, appendHookInitializer(this.hookInitializers, hooks));
4054
4083
  }
4055
4084
  instantiate(parent, subpath, environment, initialValue) {
4056
4085
  this._determineIdentifierMode();
@@ -4093,15 +4122,7 @@ class MapType extends ComplexType {
4093
4122
  }
4094
4123
  finalizeNewInstance(node, instance) {
4095
4124
  _interceptReads(instance, node.unbox);
4096
- const type = node.type;
4097
- type.hookInitializers.forEach(initializer => {
4098
- const hooks = initializer(instance);
4099
- Object.keys(hooks).forEach(name => {
4100
- const hook = hooks[name];
4101
- const actionInvoker = createActionInvoker(instance, name, hook);
4102
- (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
4103
- });
4104
- });
4125
+ installHookInitializers(node.type.hookInitializers, instance);
4105
4126
  intercept(instance, this.willChange);
4106
4127
  observe(instance, this.didChange);
4107
4128
  }
@@ -4302,9 +4323,9 @@ function isMapType(type) {
4302
4323
  */
4303
4324
  class ArrayType extends ComplexType {
4304
4325
  _subType;
4326
+ hookInitializers;
4305
4327
  flags = TypeFlags.Array;
4306
- hookInitializers = [];
4307
- constructor(_subType, hookInitializers = []) {
4328
+ constructor(_subType, hookInitializers = NO_HOOK_INITIALIZERS) {
4308
4329
  super();
4309
4330
  this._subType = _subType;
4310
4331
  this.hookInitializers = hookInitializers;
@@ -4313,10 +4334,7 @@ class ArrayType extends ComplexType {
4313
4334
  return `${this._subType.name}[]`;
4314
4335
  }
4315
4336
  hooks(hooks) {
4316
- const hookInitializers = this.hookInitializers.length > 0
4317
- ? this.hookInitializers.concat(hooks)
4318
- : [hooks];
4319
- return new ArrayType(this._subType, hookInitializers);
4337
+ return new ArrayType(this._subType, appendHookInitializer(this.hookInitializers, hooks));
4320
4338
  }
4321
4339
  instantiate(parent, subpath, environment, initialValue) {
4322
4340
  return createObjectNode(this, parent, subpath, environment, initialValue);
@@ -4336,15 +4354,7 @@ class ArrayType extends ComplexType {
4336
4354
  }
4337
4355
  finalizeNewInstance(node, instance) {
4338
4356
  _getAdministration(instance).dehancer = node.unbox;
4339
- const type = node.type;
4340
- type.hookInitializers.forEach(initializer => {
4341
- const hooks = initializer(instance);
4342
- Object.keys(hooks).forEach(name => {
4343
- const hook = hooks[name];
4344
- const actionInvoker = createActionInvoker(instance, name, hook);
4345
- (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
4346
- });
4347
- });
4357
+ installHookInitializers(node.type.hookInitializers, instance);
4348
4358
  intercept(instance, this.willChange);
4349
4359
  observe(instance, this.didChange);
4350
4360
  }
@@ -4720,8 +4730,7 @@ function getPropObservables(storedValue) {
4720
4730
  function objectTypeToString() {
4721
4731
  return getStateTreeNode(this).toString();
4722
4732
  }
4723
- const defaultObjectOptions = {
4724
- name: "AnonymousModel"};
4733
+ const ANONYMOUS_MODEL_NAME = "AnonymousModel";
4725
4734
  /**
4726
4735
  * A plain loop rather than `forAllProps`, which allocated a closure and made an
4727
4736
  * indirect call per property. This runs once per `types.model()` over every
@@ -4807,7 +4816,7 @@ class ModelType extends ComplexType {
4807
4816
  // `??`, not `||`: `types.model("", {})` names the model "". The old
4808
4817
  // `Object.assign(this, defaults, opts)` below overwrote the `||` fallback
4809
4818
  // with opts.name afterwards, so that only worked by accident.
4810
- super(opts.name ?? defaultObjectOptions.name);
4819
+ super(opts.name ?? ANONYMOUS_MODEL_NAME);
4811
4820
  // Every field is assigned here, unconditionally and in a fixed order,
4812
4821
  // rather than by `Object.assign(this, defaultObjectOptions, opts)`. `opts`
4813
4822
  // carries a different key set at each of the three call sites — `model()`,
@@ -4947,19 +4956,7 @@ class ModelType extends ComplexType {
4947
4956
  }
4948
4957
  extend(fn) {
4949
4958
  const initializer = (self) => {
4950
- const { actions, views, state, ...rest } = fn(self);
4951
- for (const key in rest) {
4952
- throw fail(`The \`extend\` function should return an object with a subset of the fields 'actions', 'views' and 'state'. Found invalid key '${key}'`);
4953
- }
4954
- if (state) {
4955
- this.instantiateVolatileState(self, state);
4956
- }
4957
- if (views) {
4958
- this.instantiateViews(self, views);
4959
- }
4960
- if (actions) {
4961
- this.instantiateActions(self, actions);
4962
- }
4959
+ this.applyExtension(self, fn(self), "The `extend` function");
4963
4960
  return self;
4964
4961
  };
4965
4962
  return this.cloneAndEnhance({ initializers: [initializer] });
@@ -4980,9 +4977,17 @@ class ModelType extends ComplexType {
4980
4977
  * are permitted (see extendInstance, which runs this in an action context).
4981
4978
  */
4982
4979
  applyExtensionToInstance(self, extension) {
4980
+ this.applyExtension(self, extension, "extendInstance");
4981
+ }
4982
+ /**
4983
+ * Materializes an `{ actions, views, state }` bundle onto an instance. Shared
4984
+ * by `.extend()` (at creation time) and `applyExtensionToInstance` (on a live
4985
+ * instance); `subject` only names the caller in the invalid-key error.
4986
+ */
4987
+ applyExtension(self, extension, subject) {
4983
4988
  const { actions, views, state, ...rest } = extension;
4984
4989
  for (const key in rest) {
4985
- throw fail(`extendInstance should return an object with a subset of the fields 'actions', 'views' and 'state'. Found invalid key '${key}'`);
4990
+ throw fail(`${subject} should return an object with a subset of the fields 'actions', 'views' and 'state'. Found invalid key '${key}'`);
4986
4991
  }
4987
4992
  if (state) {
4988
4993
  this.instantiateVolatileState(self, state);
@@ -5272,7 +5277,7 @@ function model(...args) {
5272
5277
  if (devMode() && typeof args[0] !== "string" && args[1]) {
5273
5278
  throw fail("Model creation failed. First argument must be a string when two arguments are provided");
5274
5279
  }
5275
- const name = typeof args[0] === "string" ? args.shift() : "AnonymousModel";
5280
+ const name = typeof args[0] === "string" ? args.shift() : ANONYMOUS_MODEL_NAME;
5276
5281
  const properties = args.shift() || {};
5277
5282
  return new ModelType({ name, properties });
5278
5283
  }
@@ -5286,7 +5291,7 @@ function model(...args) {
5286
5291
  function compose(...args) {
5287
5292
  // TODO: just join the base type names if no name is provided
5288
5293
  const hasTypename = typeof args[0] === "string";
5289
- const typeName = hasTypename ? args[0] : "AnonymousModel";
5294
+ const typeName = hasTypename ? args[0] : ANONYMOUS_MODEL_NAME;
5290
5295
  if (hasTypename) {
5291
5296
  args.shift();
5292
5297
  }
@@ -5512,6 +5517,12 @@ function getPrimitiveFactoryFromValue(value) {
5512
5517
  /**
5513
5518
  * Returns if a given value represents a primitive type.
5514
5519
  *
5520
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
5521
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
5522
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
5523
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
5524
+ * `isMapType`, `isModelType`) keep their predicate.
5525
+ *
5515
5526
  * @param type
5516
5527
  * @returns
5517
5528
  */
@@ -5576,6 +5587,12 @@ function literal(value) {
5576
5587
  /**
5577
5588
  * Returns if a given value represents a literal type.
5578
5589
  *
5590
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
5591
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
5592
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
5593
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
5594
+ * `isMapType`, `isModelType`) keep their predicate.
5595
+ *
5579
5596
  * @param type
5580
5597
  * @returns
5581
5598
  */
@@ -5655,6 +5672,12 @@ function refinement(...args) {
5655
5672
  /**
5656
5673
  * Returns if a given value is a refinement type.
5657
5674
  *
5675
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
5676
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
5677
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
5678
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
5679
+ * `isMapType`, `isModelType`) keep their predicate.
5680
+ *
5658
5681
  * @param type
5659
5682
  * @returns
5660
5683
  */
@@ -5992,7 +6015,8 @@ class Union extends BaseType {
5992
6015
  // - A failure is the definitive, scoped error only when every member is
5993
6016
  // discriminated; otherwise a catch-all could still accept the value, so
5994
6017
  // fall through to full validation.
5995
- if (isPlainObject(value) && !isStateTreeNode(value)) {
6018
+ const isSnapshotObject = isPlainObject(value) && !isStateTreeNode(value);
6019
+ if (isSnapshotObject) {
5996
6020
  const discriminator = value.type;
5997
6021
  if (typeof discriminator === "string") {
5998
6022
  const candidate = this._findCandidateByTypeDiscriminator(discriminator);
@@ -6008,7 +6032,7 @@ class Union extends BaseType {
6008
6032
  // for plain-object snapshots, prefer union members whose literal-typed
6009
6033
  // discriminator properties match the value (e.g. {type: "MsaView"})
6010
6034
  // so error output is scoped to the intended branch instead of every member
6011
- const candidates = isPlainObject(value) && !isStateTreeNode(value)
6035
+ const candidates = isSnapshotObject
6012
6036
  ? this._types.filter(t => this.snapshotLooksLikeType(value, t))
6013
6037
  : [];
6014
6038
  const typesToValidate = candidates.length > 0 ? candidates : this._types;
@@ -6078,6 +6102,12 @@ function union(...args) {
6078
6102
  /**
6079
6103
  * Returns if a given value represents a union type.
6080
6104
  *
6105
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
6106
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
6107
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
6108
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
6109
+ * `isMapType`, `isModelType`) keep their predicate.
6110
+ *
6081
6111
  * @param type
6082
6112
  * @returns
6083
6113
  */
@@ -6256,6 +6286,12 @@ const undefinedAsOptionalValues = [undefined];
6256
6286
  /**
6257
6287
  * Returns if a value represents an optional type.
6258
6288
  *
6289
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
6290
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
6291
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
6292
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
6293
+ * `isMapType`, `isModelType`) keep their predicate.
6294
+ *
6259
6295
  * @template IT
6260
6296
  * @param type
6261
6297
  * @returns
@@ -6502,6 +6538,12 @@ function late(nameOrType, maybeType) {
6502
6538
  /**
6503
6539
  * Returns if a given value represents a late type.
6504
6540
  *
6541
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
6542
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
6543
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
6544
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
6545
+ * `isMapType`, `isModelType`) keep their predicate.
6546
+ *
6505
6547
  * @param type
6506
6548
  * @returns
6507
6549
  */
@@ -6670,6 +6712,12 @@ function frozen(arg) {
6670
6712
  /**
6671
6713
  * Returns if a given value represents a frozen type.
6672
6714
  *
6715
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
6716
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
6717
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
6718
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
6719
+ * `isMapType`, `isModelType`) keep their predicate.
6720
+ *
6673
6721
  * @param type
6674
6722
  * @returns
6675
6723
  */
@@ -6900,9 +6948,6 @@ class BaseReferenceType extends SimpleType {
6900
6948
  * @hidden
6901
6949
  */
6902
6950
  class IdentifierReferenceType extends BaseReferenceType {
6903
- constructor(targetType, onInvalidated) {
6904
- super(targetType, onInvalidated);
6905
- }
6906
6951
  getValue(storedRefNode) {
6907
6952
  if (!storedRefNode.isAlive) {
6908
6953
  return undefined;
@@ -7018,6 +7063,12 @@ function reference(subType, options) {
7018
7063
  /**
7019
7064
  * Returns if a given value represents a reference type.
7020
7065
  *
7066
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
7067
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
7068
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
7069
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
7070
+ * `isMapType`, `isModelType`) keep their predicate.
7071
+ *
7021
7072
  * @param type
7022
7073
  * @returns
7023
7074
  */
@@ -7150,6 +7201,12 @@ const identifierNumber = new IdentifierNumberType();
7150
7201
  /**
7151
7202
  * Returns if a given value represents an identifier type.
7152
7203
  *
7204
+ * Returns a plain `boolean`, not a `type is IT` predicate: with the parameter
7205
+ * typed as `IT`, narrowing to `IT` was a no-op in the positive branch while
7206
+ * collapsing the negative one to `never`, so `if (!isX(t)) { t.name }` failed
7207
+ * to compile. Guards with a distinct narrowing target (`isArrayType`,
7208
+ * `isMapType`, `isModelType`) keep their predicate.
7209
+ *
7153
7210
  * @param type
7154
7211
  * @returns
7155
7212
  */