microsoft/TypeScript · error · TypeError
Private accessor was defined without a getter
Error message
Private accessor was defined without a getter
What it means
Runtime TypeError thrown by the `__classPrivateFieldGet` downlevel helper that TypeScript emits when transpiling private accessors to targets below ES2022. The helper throws when `kind === "a"` (an accessor) but no getter function `f` was passed — i.e. the private accessor is write-only (declared with only a `set`). The compiler never throws this; only the emitted JavaScript does, when the write-only accessor is read.
Source
Thrown at src/compiler/factory/emitHelpers.ts:1287
* __classPrivateFieldGet(<any>, <constructor>, "f", <{ value: any }>)
*
* Reading from a private static get accessor (when defined, TS 4.3+):
* __classPrivateFieldGet(<any>, <constructor>, "a", <function>)
*
* Reading from a private static get accessor (when not defined, TS 4.3+):
* __classPrivateFieldGet(<any>, <constructor>, "a", void 0)
* NOTE: This always results in a runtime error.
*
* Reading from a private static method (TS 4.3+):
* __classPrivateFieldGet(<any>, <constructor>, "m", <function>)
*/
const classPrivateFieldGetHelper: UnscopedEmitHelper = {
name: "typescript:classPrivateFieldGet",
importName: "__classPrivateFieldGet",
scoped: false,
text: `
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};`,
};
/**
* Parameters:
* @param receiver — The object on which the private member will be set.
* @param state — One of the following:
* - A WeakMap used to store a private instance field.
* - A WeakSet used as an instance brand for private instance methods and accessors.
* - A function value that should be the undecorated class constructor used to brand check private static fields, methods, and accessors.
* @param value — The value to set.
* @param kind — (optional pre TS 4.3, required for TS 4.3+) One of the following values:
* - undefined — Indicates a private instance field (pre TS 4.3).
* - "f" — Indicates a private field (instance or static).
* - "m" — Indicates a private method (instance or static).
* - "a" — Indicates a private accessor (instance or static).
View on GitHub (pinned to b465fdbfe1)
Solutions
- Add a `get` accessor to the private member so reads are valid.
- Raise `target` to `ES2022`+ so native private fields are emitted and the helper is not generated.
- Stop reading the write-only accessor at that call site — only assign to it.
- If invoking the helper manually, pass a non-null getter function for kind "a".
Example fix
// before
class C {
set #acc(v: number) {} // setter only, no getter
read() { return this.#acc; } // runtime TypeError
}
// after
class C {
#v = 0;
get #acc() { return this.#v; }
set #acc(v: number) { this.#v = v; }
read() { return this.#acc; }
} Defensive patterns
Strategy: type-guard
Validate before calling
// At authoring time the compiler flags reads of write-only accessors.
// If you bypassed types with `any`, restore them so the read is caught statically:
function readAcc(c: C) { return (c as any).#acc; } // avoid `any` casts on private members Type guard
// Ensure every private accessor you read has a getter (compile-time):
type HasGetter<T> = T extends { readonly get: infer G } ? G : never; Prevention
- Keep `target` >= ES2022 when using private accessors to avoid the helper entirely.
- Never read a private member through `any`; the type system is what prevents this.
- When adding a private setter, add the matching getter unless write-only is intentional and never read.
When it happens
Trigger: Reading a private accessor that has only a setter (`set #x(v){}` with no `get #x`), in code compiled with the `__classPrivateFieldGet` helper (target below ES2022, or downlevel private-member emit). Also reached by calling the helper directly with kind "a" and a falsy fourth argument.
Common situations: Downleveling a class that contains a setter-only private accessor and then reading that accessor from a method; refactoring a public accessor pair into private members and forgetting the getter; targeting older runtimes while using ES2022 private syntax.
Related errors
- Private accessor was defined without a setter
- Cannot read private member from an object whose class did no
- Private method is not writable
- Cannot write private member to an object whose class did not
- Cannot use 'in' operator on non-object
AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12).
Data as JSON: /api/errors/cacd6eb4d35e45c0.
Report an issue: GitHub.