can1357/oh-my-pi · error · OmpTypeError
intersection of ${a.expected} and ${b.expected} is unsatisfi
Error message
intersection of ${a.expected} and ${b.expected} is unsatisfiable What it means
When intersecting two instance types (constructed via instanceof-style checks), the library returns the narrower constructor if one is a subclass of the other. If the constructors are unrelated (neither prototype chain contains the other), no value can be an instance of both, so it throws with the human-readable expected names of both types.
Source
Thrown at packages/omptype/src/type.ts:2126
xmin,
xmax,
};
}
if (a.k === "array" && b.k === "array") {
const min = maxOf(a.min, b.min);
const max = minOf(a.max, b.max);
if (min !== undefined && max !== undefined && min > max) {
throw new OmpTypeError("array length intersection is unsatisfiable");
}
return { k: "array", el: intersect(a.el, b.el), min, max };
}
if (a.k === "tuple" && b.k === "tuple") return intersectTuples(a, b);
if (a.k === "tuple" && b.k === "array") return intersectTupleWithArray(a, b);
if (a.k === "array" && b.k === "tuple") return intersectTupleWithArray(b, a);
if (a.k === "instance" && b.k === "instance") {
if (a.ctor === b.ctor || a.ctor.prototype instanceof b.ctor) return a;
if (b.ctor.prototype instanceof a.ctor) return b;
throw new OmpTypeError(`intersection of ${a.expected} and ${b.expected} is unsatisfiable`);
}
if (a.k === b.k && ["null", "undefined", "boolean", "bigint", "symbol", "anyobject"].includes(a.k)) return a;
if (
(a.k === "object" && (b.k === "array" || b.k === "tuple")) ||
(b.k === "object" && (a.k === "array" || a.k === "tuple"))
) {
return { k: "intersection", members: [a, b] };
}
const leftDomain = domainOf(a);
const rightDomain = domainOf(b);
if (leftDomain !== undefined && rightDomain !== undefined && leftDomain !== rightDomain) {
throw new OmpTypeError(`intersection of ${leftDomain} and ${rightDomain} is unsatisfiable`);
}
if (a.k === "anyobject" && rightDomain === "object") return b;
if (b.k === "anyobject" && leftDomain === "object") return a;
const members = [...(a.k === "intersection" ? a.members : [a]), ...(b.k === "intersection" ? b.members : [b])];
return { k: "intersection", members };
}View on GitHub (pinned to 9690622007)
Solutions
- Use the common subclass if one actually extends the other
- Replace the intersection with a union if either instance is acceptable
- Model the constraint with a single class or an object/structural type instead of two instance checks
- Deduplicate class copies so the same constructor identity is used
Example fix
// before intersect(instance(Error), instance(TypeError)); // TypeError extends Error: OK intersect(instance(Error), instance(Map)); // throws // after intersect(instance(TypeError), instance(Error)); // subtype first, or intersect related ctors only
Defensive patterns
Strategy: type-guard
Validate before calling
function instancesCompatible(a, b) {
return a.ctor === b.ctor || a.ctor.prototype instanceof b.ctor || b.ctor.prototype instanceof a.ctor;
} Type guard
const isOmpTypeError = (e: unknown): e is OmpTypeError => e instanceof OmpTypeError;
Try / catch
try {
const t = intersect(instanceA, instanceB);
} catch (err) {
if (err instanceof OmpTypeError && err.message.includes('is unsatisfiable')) {
// use a union or a structural (object) type instead
} else throw err;
} Prevention
- Only intersect classes in a genuine subclass relationship
- Avoid duplicate copies of the same class (dual installs/bundles) — they break prototype-chain checks
- Prefer structural (object) types over instanceof when you only care about shape
When it happens
Trigger: intersect(instance(Date), instance(Map)); or intersecting a class with an unrelated class after a refactor renamed/moved one; two versioned copies of the same class from different module instances (prototype chains differ).
Common situations: Refinements asserting instanceof checks on classes that were never in a subclass relationship; duplicate class copies from multiple bundler chunks or dual package installs; intersecting a base-class refinement with a sibling-class refinement.
Related errors
- intersection has no satisfiable branches
- literal is excluded by the intersection
- ParseError: Invalid intersection of default values ${String(
- intersection of ${leftDomain} and ${rightDomain} is unsatisf
- tuple length intersection is unsatisfiable
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/47685aaa347140bb.
Report an issue: GitHub.