microsoft/TypeScript · error · TypeError

Cannot write private member to an object whose class did not

Error message

Cannot write private member to an object whose class did not declare it

What it means

Runtime TypeError from `__classPrivateFieldSet`, the write-path brand check. After the kind checks pass, the helper requires `state.has(receiver)` (instance) or `receiver === state` (static). If the receiver was not branded by the declaring class, the write is rejected. Mirror of error 21 on the write path.

Source

Thrown at src/compiler/factory/emitHelpers.ts:1352

 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "a", <function>)
 *
 * Writing to a private static set accessor (when not defined, TS 4.3+):
 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "a", void 0)
 *      NOTE: This always results in a runtime error.
 *
 * Writing to a private static method (TS 4.3+):
 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "m", <function>)
 *      NOTE: This always results in a runtime error.
 */
const classPrivateFieldSetHelper: UnscopedEmitHelper = {
    name: "typescript:classPrivateFieldSet",
    importName: "__classPrivateFieldSet",
    scoped: false,
    text: `
            var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
                if (kind === "m") throw new TypeError("Private method is not writable");
                if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
                if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
                return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
            };`,
};

/**
 * Parameters:
 *  @param state — One of the following:
 *      - A WeakMap when the member is a private instance field.
 *      - A WeakSet when the member is a private instance method or accessor.
 *      - A function value that should be the undecorated class constructor when the member is a private static field, method, or accessor.
 *  @param receiver — The object being checked if it has the private member.
 *
 * Usage:
 * This helper is used to transform `#field in expression` to
 *      `__classPrivateFieldIn(<weakMap/weakSet/constructor>, expression)`
 */
const classPrivateFieldInHelper: UnscopedEmitHelper = {
    name: "typescript:classPrivateFieldIn",

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Ensure the receiver is a genuine instance built by `new C()`.
  2. Type setter parameters as the declaring class so alien receivers fail at compile time.
  3. Rehydrate deserialized data into class instances before calling setters.
  4. For static privates, invoke on the class constructor itself.

Example fix

// before
class C {
  #x = 0;
  static set(o: any, v: number) { o.#x = v; }  // alien object throws
}
C.set(Object.create(C.prototype), 9);
// after
class C {
  #x = 0;
  static set(o: C, v: number) { o.#x = v; }
}
const c = new C();
C.set(c, 9);
Defensive patterns

Strategy: validation

Validate before calling

function safeSet(o: unknown, v: number) { if (o instanceof C) { (o as C).#x = v; } }

Type guard

function isC(o: unknown): o is C { return o instanceof C; }

Prevention

When it happens

Trigger: Assigning to a private member through a method invoked on an alien receiver (`C.prototype.setter.call(plainObj, v)`), or writing a static private member on something that is not the class constructor. Typically reached through `as any`, `Object.create`, or deserialized objects.

Common situations: Hydrating objects via `JSON.parse` and calling setters on them; proxy/subclass machinery that does not run the class constructor; cross-class helpers that accept `any`.

Related errors


AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12). Data as JSON: /api/errors/069a8d84a3433446. Report an issue: GitHub.