pydantic/monty · error · TypeError
ClassType expects a class (constructor function)
Error message
ClassType expects a class (constructor function)
What it means
ClassType wraps a host class so it can cross into the Monty sandbox (and optionally be instantiated there with init: true). Its constructor validates up front that the value is actually a class — a constructor function — and throws this TypeError for anything else (plain objects, class instances, primitives, arrow functions without constructor semantics used as classes).
Source
Thrown at crates/monty-js/ts/classInstance.ts:285
*
* ```ts
* await session.feedRun('p = Point(1, 2)\nassert p.x == 1', {
* inputs: { Point: new ClassType(Point, { init: true, instanceEagerAttrs: 'all' }) },
* })
* ```
*/
export class ClassType extends BaseWrapper {
/** The class's sandbox identity. Defaults to a process-wide id per class
* object (every wrapper of one class agrees), so instances keep a stable
* type identity; pass `id` to pin it explicitly, e.g. when restoring a
* dump in a fresh process. */
readonly id: string
declare readonly options: ClassTypeOptions
constructor(classType: new (...args: never[]) => object, options: ClassTypeOptions = {}) {
if (typeof classType !== 'function') {
throw new TypeError('ClassType expects a class (constructor function)')
}
super(classType, options)
validatePolicy('instanceEagerAttrs', options.instanceEagerAttrs)
validatePolicy('instanceLazyAttrs', options.instanceLazyAttrs)
validatePolicy('instanceAllowedMethods', options.instanceAllowedMethods)
this.id = options.id === undefined ? classIdFor(classType) : normalizeId('ClassType', options.id)
}
/** The wrapped host class (the inherited `instance` field). */
get classType(): new (...args: never[]) => object {
return this.instance as new (...args: never[]) => object
}
/** Class name shown to the sandbox: `options.name`, else the class name. */
override getName(): string {
if (this.options.name !== undefined) {
return this.options.name
}View on GitHub (pinned to adc986b362)
Solutions
- Pass the class itself, not an instance: `new ClassType(Point, ...)` instead of `new ClassType(new Point(), ...)`.
- Check `typeof value === 'function'` and that it has a prototype before wrapping.
- If the value is a plain factory function, convert it to a class or wrap instances of its results individually with ClassInstance.
- Verify imports resolve to the class (check for wrong default/named import or undefined under ESM circular imports).
Example fix
// before
const point = new Point(1, 2)
new ClassType(point, { init: true }) // TypeError
// after
new ClassType(Point, { init: true, instanceEagerAttrs: 'all' }) Defensive patterns
Strategy: validation
Validate before calling
function isClass(value: unknown): value is new (...args: never[]) => object {
return typeof value === 'function' && /^class\s/.test(Function.prototype.toString.call(value))
}
if (!isClass(maybeClass)) throw new TypeError('ClassType requires a class constructor') Type guard
function isConstructorFunction(value: unknown): value is new (...args: never[]) => object {
if (typeof value !== 'function') return false
const desc = Object.getOwnPropertyDescriptor(value, 'prototype')
return desc !== undefined && !desc.writable // class constructors have non-writable prototype
} Try / catch
try {
const type = new ClassType(value, { init: true })
} catch (e) {
if (e instanceof TypeError && /expects a class/.test(e.message)) {
throw new TypeError(`${debugName(value)} is not a class — pass the constructor, not an instance`)
} else throw e
} Prevention
- Type parameters as `new (...args: never[]) => object` so TS rejects non-constructor values at compile time
- Remember Point vs new Point — always wrap the class object
- Verify imports: a wrong default import may yield undefined or an object at runtime
- Plain factory functions are not classes; convert them or wrap their products with ClassInstance instead
When it happens
Trigger: `new ClassType(point)` passing an instance instead of the class; `new ClassType(configObject)` passing a plain object; `new ClassType(null/undefined)`; passing something read out of a loosely typed registry or JSON config where the class was expected.
Common situations: Confusing the class with its instance (Point vs new Point()); importing a default export that is an object, not a class; typos resolving to undefined under a permissive tsconfig; trying to wrap a plain factory function that is not a constructor.
Related errors
- classType does not match the instance's class
- ClassInstance expects an object instance
- ClassInstance expects an instance of a class, not a null-pro
- pass name on the ClassType wrapper, not alongside classType
- Cannot convert ${constructorName(value)} instance to a Monty
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/92d7039b6b2e2f7f.
Report an issue: GitHub.