{"record":{"id":"319bd8c544a11365","repo":"pydantic/monty","slug":"pass-name-on-the-classtype-wrapper-not-alongside-classtype","errorCode":null,"errorMessage":"pass name on the ClassType wrapper, not alongside classType","messagePattern":"pass name on the ClassType wrapper, not alongside classType","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/classInstance.ts","lineNumber":224,"sourceCode":"   *  `options.classType` if given, else a default one materialized from the\n   *  constructor. */\n  readonly classType: ClassType\n\n  declare readonly options: ClassInstanceOptions\n\n  constructor(instance: object, options: ClassInstanceOptions = {}) {\n    super(instance, options)\n    this.id = options.id === undefined ? generateUuid() : normalizeId('ClassInstance', options.id)\n    const ctor = classOf(instance)\n    if (ctor === undefined) {\n      throw new TypeError('ClassInstance expects an instance of a class, not a null-prototype object')\n    }\n    if (options.classType !== undefined) {\n      if (options.classType.classType !== ctor) {\n        throw new TypeError(\"classType does not match the instance's class\")\n      }\n      if (options.name !== undefined) {\n        throw new TypeError('pass name on the ClassType wrapper, not alongside classType')\n      }\n      this.classType = options.classType\n    } else {\n      this.classType = new ClassType(ctor as new (...args: never[]) => object, { name: options.name })\n    }\n  }\n\n  /** Class name shown to the sandbox: the class wrapper's, so the instance,\n   *  its type object and error messages all agree. */\n  override getName(): string {\n    return this.classType.getName()\n  }\n}\n\n/** Options for [`ClassType`]: the inherited policies applied to the class\n *  object itself (class constants, static methods), the `init` gate, and the\n *  `instance*` policies applied to every constructed instance. */\nexport interface ClassTypeOptions extends BaseWrapperOptions {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/classInstance.ts#L206-L242","documentation":"When both classType and name are passed to ClassInstance, this TypeError is thrown: the name is a class-level property, and once an explicit ClassType wrapper is provided the display name must be set on that wrapper, not duplicated at the instance level. This keeps the instance, its type object and error messages all reporting one consistent name.","triggerScenarios":"`new ClassInstance(user, { classType: userType, name: 'User' })` — passing name alongside an explicit classType wrapper.","commonSituations":"Copy-pasting options between the two construction styles (with and without classType); switching from the default (auto-materialized) ClassType to an explicit one and leaving the old `name` option in place.","solutions":["Move the name onto the ClassType wrapper: `new ClassType(User, { name: 'User' })` and drop `name` from ClassInstanceOptions.","Remove the `name` option from the ClassInstance call when classType is present.","If no class-level policies are needed, drop classType instead and keep `name` — the default ClassType will be built with that name."],"exampleFix":"// before\nnew ClassInstance(user, { classType: userType, name: 'User' }) // TypeError\n// after\nconst userType = new ClassType(User, { name: 'User' })\nnew ClassInstance(user, { classType: userType })","handlingStrategy":"validation","validationCode":"function classInstanceOptions(instance: object, opts: { classType?: ClassType; name?: string }) {\n  if (opts.classType !== undefined && opts.name !== undefined) {\n    throw new TypeError('pass name on the ClassType wrapper, not alongside classType')\n  }\n  return opts\n}","typeGuard":null,"tryCatchPattern":"try {\n  wrapper = new ClassInstance(user, opts)\n} catch (e) {\n  if (e instanceof TypeError && /pass name on the ClassType wrapper/.test(e.message)) {\n    const { name, ...rest } = opts\n    wrapper = new ClassInstance(user, { ...rest, classType: new ClassType(user.constructor, { name }) })\n  } else throw e\n}","preventionTips":["Set name on the ClassType wrapper whenever you pass an explicit classType","Keep a single helper that builds the (ClassType, ClassInstance) pair so options land in one place","When migrating from name-only to classType usage, delete the name field, don't keep both","Read ClassInstanceOptions.name docs: it only names the auto-materialized default ClassType"],"tags":["typescript","configuration","mutually-exclusive","wrapper"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}