can1357/oh-my-pi · error · OmpTypeError

instanceof operands must be constructors

Error message

instanceof operands must be constructors

What it means

`type.instanceOf(ctor)` validates that its argument is an actual constructor function — something invokable with `new` and having a prototype. Passing a non-function, arrow function, or a bound function with `undefined` prototype cannot be used for `instanceof` checks, so omptype throws.

Source

Thrown at packages/omptype/src/type.ts:3576

		},
		object: {
			json: Object.defineProperties(keywordSchema<unknown>("object.json"), {
				stringify: {
					value: keywordSchema<string, unknown>("object.json.stringify"),
					enumerable: true,
				},
			}),
		},
		unknown: { any: keywordSchema<unknown>("unknown.any") },
	};
	/** Date instance validator. */
	// biome-ignore lint/suspicious/noShadowRestrictedNames: ArkType exposes this exact keyword.
	export const Date = makeType<globalThis.Date>({ k: "instance", ctor: globalThis.Date, expected: "a Date" }, [], {});

	/** Validate instances of `ctor`. */
	export function instanceOf<const ctor extends Constructor>(ctor: ctor): FluentType<Constructed<ctor>> {
		if (typeof ctor !== "function" || ctor.prototype === undefined) {
			throw new OmpTypeError("instanceof operands must be constructors");
		}
		const name = Reflect.get(ctor, "name");
		const expected =
			ctor.prototype === Error.prototype
				? "an Error"
				: typeof name === "string" && name.length > 0
					? `an instance of ${name}`
					: "an instance";
		return makeType<Constructed<ctor>>({ k: "instance", ctor, expected }, [], {});
	}

	/** Validate one exact unit value. */
	export function unit<const value>(value: value): FluentType<value> {
		return makeType<value>({ k: "lit", v: value }, [], {});
	}

	/** Union of literal values from a runtime array. */
	export function enumerated<const values extends readonly unknown[]>(...values: values): FluentType<values[number]> {

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass the class/constructor itself: `type.instanceOf(Date)`, not an instance.
  2. Defer schema construction until the class module is fully loaded (avoid circular-import init-time construction).
  3. For bound or arrow constructs, use a regular class or `type(() => v instanceof Target)` predicate instead.

Example fix

// before
type.instanceOf(new Date())
// after
type.instanceOf(Date)
Defensive patterns

Strategy: validation

Validate before calling

function isConstructor(v: unknown): boolean { return typeof v === 'function' && v.prototype !== undefined; }

Type guard

const isCtor = (v: unknown): v is abstract new (...args: never[]) => unknown => typeof v === 'function' && v.prototype !== undefined;

Try / catch

try { const t = type.instanceOf(maybeCtor); } catch (e) { if (e instanceof OmpTypeError) deferSchemaConstruction(); else throw e; }

Prevention

When it happens

Trigger: Calling `type.instanceOf(SomeArrowFn)`, `type.instanceOf({})`, `type.instanceOf(obj.bind(...))` (bound functions have no `.prototype`), or passing a class imported as `undefined` due to a circular import.

Common situations: Circular imports leaving a class undefined at module-init time when the schema is built at top level; accidentally passing an instance instead of its class (`type.instanceOf(new Date())`); classes defined in a different module graph not yet loaded.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/b3f6497718978227. Report an issue: GitHub.