{"record":{"id":"bad8fcb097571296","repo":"microsoft/TypeScript","slug":"cannot-read-private-member-from-an-object-whose-cl","errorCode":null,"errorMessage":"Cannot read private member from an object whose class did not declare it","messagePattern":"Cannot read private member from an object whose class did not declare it","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/compiler/factory/emitHelpers.ts","lineNumber":1288,"sourceCode":" *\r\n * Reading from a private static get accessor (when defined, TS 4.3+):\r\n *      __classPrivateFieldGet(<any>, <constructor>, \"a\", <function>)\r\n *\r\n * Reading from a private static get accessor (when not defined, TS 4.3+):\r\n *      __classPrivateFieldGet(<any>, <constructor>, \"a\", void 0)\r\n *      NOTE: This always results in a runtime error.\r\n *\r\n * Reading from a private static method (TS 4.3+):\r\n *      __classPrivateFieldGet(<any>, <constructor>, \"m\", <function>)\r\n */\r\nconst classPrivateFieldGetHelper: UnscopedEmitHelper = {\r\n    name: \"typescript:classPrivateFieldGet\",\r\n    importName: \"__classPrivateFieldGet\",\r\n    scoped: false,\r\n    text: `\r\n            var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n                if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n                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\");\r\n                return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n            };`,\r\n};\r\n\r\n/**\r\n * Parameters:\r\n *  @param receiver — The object on which the private member will be set.\r\n *  @param state — One of the following:\r\n *      - A WeakMap used to store a private instance field.\r\n *      - A WeakSet used as an instance brand for private instance methods and accessors.\r\n *      - A function value that should be the undecorated class constructor used to brand check private static fields, methods, and accessors.\r\n *  @param value — The value to set.\r\n *  @param kind — (optional pre TS 4.3, required for TS 4.3+) One of the following values:\r\n *       - undefined — Indicates a private instance field (pre TS 4.3).\r\n *       - \"f\" — Indicates a private field (instance or static).\r\n *       - \"m\" — Indicates a private method (instance or static).\r\n *       - \"a\" — Indicates a private accessor (instance or static).\r\n *   @param f — (optional pre TS 4.3) Depends on the arguments for state and kind:\r","sourceCodeStart":1270,"sourceCodeEnd":1306,"githubUrl":"https://github.com/microsoft/TypeScript/blob/b465fdbfe175304d9b977da137b2c178ae1091d3/src/compiler/factory/emitHelpers.ts#L1270-L1306","documentation":"Runtime TypeError from `__classPrivateFieldGet`. After resolving accessor/method kind, the helper performs a brand check: for instance members it requires `state.has(receiver)` (a WeakMap/WeakSet hit), and for static members it requires `receiver === state` (the class constructor). If the receiver was not constructed by the declaring class (or is not the class itself for statics), the brand check fails and this is thrown.","triggerScenarios":"Accessing a private instance member on an object that was not constructed by the declaring class (e.g. `C.prototype.method.call(alienObject)` where the method reads `this.#x`), or passing the wrong constructor for a private static member. Common via `as any` casts, `Object.create(C.prototype)`, or cross-class helper calls.","commonSituations":"Calling a method that reads a private field on an object obtained through `Object.create`, structural casts, or deserialization (`JSON.parse` produces plain objects with no branding); subclass/superclass wiring that bypasses constructors; static private access from a non-class receiver.","solutions":["Make sure the receiver is a real instance produced by `new C()`.","Type the parameter as the declaring class (`o: C`) so alien receivers are rejected at compile time.","When deserializing, rehydrate into a class instance before invoking private-reading methods.","For static private members, call on the class constructor itself, not a copy."],"exampleFix":"// before\nclass C {\n  #x = 1;\n  static read(o: any) { return o.#x; }   // {} as any throws at runtime\n}\nC.read({} as any);\n// after\nclass C {\n  #x = 1;\n  static read(o: C) { return o.#x; }     // typed receiver\n  static isC(o: unknown): o is C { return o instanceof C; }\n}\nconst c = new C();\nC.read(c);","handlingStrategy":"validation","validationCode":"// Validate the receiver was constructed by the class before touching privates:\nfunction safeRead(o: unknown): number | undefined {\n  return o instanceof C ? (o as C).#x : undefined;\n}","typeGuard":"function isC(o: unknown): o is C { return o instanceof C; }","tryCatchPattern":null,"preventionTips":["Never pass deserialized plain objects into methods that read private members — reconstruct instances first.","Avoid `as any` on receivers of private-member methods.","Prefer static methods that take a typed `C` parameter over duck-typed callers."],"tags":["private-fields","runtime","downlevel","brand-check","emit-helpers"],"backgroundTag":null,"analyzedSha":"b465fdbfe175304d9b977da137b2c178ae1091d3","analyzedAt":"2026-08-12T05:38:42.698Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}