{"record":{"id":"6f447967851d8224","repo":"mobxjs/mobx","slug":"unexpected-type","errorCode":null,"errorMessage":"Unexpected type","messagePattern":"Unexpected type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mobx-undecorate/src/undecorate.ts","lineNumber":442,"sourceCode":"        ])\n        return property\n    }\n\n    function createConstructor(\n        clazz: ClassDeclaration,\n        members: ObjectExpression,\n        privates: string[]\n    ) {\n        // makeObservable(this, { members })\n        const initializeObservablesCall = j.expressionStatement(\n            j.callExpression(\n                j.identifier(\"makeObservable\"),\n                options?.keepDecorators ? [j.thisExpression()] : [j.thisExpression(), members]\n            )\n        )\n        if (privates.length && !options?.keepDecorators) {\n            if (typeof clazz.id!.name !== \"string\") {\n                throw new Error(\"Unexpected type\")\n            }\n            // @ts-ignore\n            initializeObservablesCall.expression.typeArguments = j.tsTypeParameterInstantiation([\n                j.tsTypeReference(j.identifier(clazz.id!.name)),\n                j.tsUnionType(\n                    // @ts-ignore\n                    privates.map(member => j.tsLiteralType(j.stringLiteral(member)))\n                )\n            ])\n        }\n\n        const needsSuper = !!clazz.superClass\n        let constructorIndex = clazz.body.body.findIndex(\n            member => j.ClassMethod.check(member) && member.kind === \"constructor\"\n        )\n\n        // create a constructor\n        if (constructorIndex === -1) {","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/mobxjs/mobx/blob/01211a698b64ea94de8e5f276ff8235fcf8ddf96/packages/mobx-undecorate/src/undecorate.ts#L424-L460","documentation":"In the codemod that rewrites legacy decorators to makeObservable calls, when a class has private members the generated initializeObservables call needs the class name as a type argument. If the class node has no simple identifier name (e.g. an anonymous or complex class expression), the transform cannot produce the type reference and throws 'Unexpected type'.","triggerScenarios":"Running the mobx-undecorate transform on a source file containing a class with private fields and a class node whose `id` is not a named identifier (anonymous class expression or otherwise unnamed class).","commonSituations":"Running npx mobx-undecorate --keepDecorators=false over codebases containing default-exported anonymous classes or class expressions assigned to variables; generated/minified input class definitions.","solutions":["Give the class an explicit name before running the transform (e.g. assign the class expression to a named variable or declare a named class)","Use `npx mobx-undecorate --keepDecorators` so the private-member makeObservable path with type arguments is skipped","Manually rewrite the decorators to makeObservable for the offending class and exclude it from the codemod"],"exampleFix":"// before\nexport default class {\n    @observable private x = 1\n}\n// after\nclass MyStore {\n    @observable private x = 1\n}\nexport default MyStore","handlingStrategy":"validation","validationCode":"// before running the codemod, ensure classes are named\nconst files = glob('src/**/*.ts(x)')\nfor (const f of files) {\n    if (/class\\s*(\\{|extends)/.test(read(f))) console.warn(`${f}: anonymous class found — name it before undecorate`)\n}","typeGuard":"function isNamedClass(node: any): boolean {\n    return node?.id?.type === 'Identifier' && typeof node.id.name === 'string'\n}","tryCatchPattern":"try {\n    runCodemod(files)\n} catch (e) {\n    if (e.message === 'Unexpected type') {\n        console.error('Codemod hit an unnamed class; name all classes with private members and rerun')\n    } else throw e\n}","preventionTips":["Avoid anonymous class expressions in decorator-heavy code","Pre-declare class names before running mobx-undecorate","Run the codemod on one directory at a time to isolate failures","Use --keepDecorators when private members are present"],"tags":["codemod","decorators","typescript","ast"],"backgroundTag":"codemod-unnamed-class","analyzedSha":"01211a698b64ea94de8e5f276ff8235fcf8ddf96","analyzedAt":"2026-08-28T22:10:08.831Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}