microsoft/TypeScript · error · TypeError

Private method is not writable

Error message

Private method is not writable

What it means

Runtime TypeError from `__classPrivateFieldSet`. The helper throws immediately when `kind === "m"` (method): private methods are non-writable by design, so any assignment to one is rejected. Emitted for targets below ES2022; on native targets the same operation throws a different (spec-defined) TypeError.

Source

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

 *
 * Writing to a private static set accessor (when defined, TS 4.3+):
 *      __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)`
 */

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Replace the private method with a private field holding a function if you genuinely need reassignment.
  2. Refactor so behavior varies through a settable dependency rather than reassigning the method.
  3. For tests, design seams (overridable protected methods, dependency injection) instead of patching privates.
  4. Raise `target` to ES2022+ to get the spec error directly, which is clearer in stack traces.

Example fix

// before
class C {
  #m() { return 1; }
  patch() { this.#m = () => 2; }  // runtime TypeError
}
// after
class C {
  #m: () => number = () => 1;     // private field holding a function
  patch() { this.#m = () => 2; }
}
Defensive patterns

Strategy: validation

Validate before calling

// Disallow assignment to private methods at design time; if reassignment is needed,
// model the slot as a field-typed function (see exampleFix).

Type guard

type IsMethod<T> = T extends (...a: any[]) => any ? true : false;

Prevention

When it happens

Trigger: Assigning to a private method (`this.#m = fn`), in code compiled with the `__classPrivateFieldSet` helper. Reached both for instance and static private methods (`#m() {}` or `static #m() {}`).

Common situations: Attempting to swap/stub a private method for testing; refactor that confuses a private method with a private field; framework code that tries to monkey-patch methods on instances.

Related errors


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