{"record":{"id":"1e5544dd94d9fba4","repo":"angular/angular","slug":"unsupported-property-access-for-type-reference","errorCode":null,"errorMessage":"Unsupported property access for type reference: ${expression.property.type}","messagePattern":"Unsupported property access for type reference: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/compiler-cli/linker/babel/src/ast/babel_ast_factory.ts","lineNumber":386,"sourceCode":"      node.typeAnnotation = t.tsTypeAnnotation(type);\n    }\n\n    return node;\n  }\n}\n\nfunction getEntityTypeFromExpression(\n  expression: t.Expression | t.Super,\n): t.Identifier | t.TSQualifiedName {\n  if (t.isIdentifier(expression)) {\n    return expression;\n  }\n\n  if (t.isMemberExpression(expression)) {\n    const left = getEntityTypeFromExpression(expression.object);\n\n    if (!t.isIdentifier(expression.property)) {\n      throw new Error(\n        `Unsupported property access for type reference: ${expression.property.type}`,\n      );\n    }\n\n    return t.tsQualifiedName(left, expression.property);\n  }\n\n  throw new Error(`Unsupported expression for type reference: ${expression.type}`);\n}\n\nfunction isLExpression(expr: t.Expression): expr is Extract<t.LVal, t.Expression> {\n  // Some LVal types are not expressions, which prevents us from using `t.isLVal()`\n  // directly with `assert()`.\n  return t.isLVal(expr);\n}\n","sourceCodeStart":368,"sourceCodeEnd":402,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/compiler-cli/linker/babel/src/ast/babel_ast_factory.ts#L368-L402","documentation":"Thrown by the Babel AST factory of the Angular partial-declaration linker when it converts a type/entity reference from partially compiled code into a static TypeScript qualified name. Walking a member expression such as `Ns.Comp` requires the property part (`.Comp`) to be an identifier; a computed access (`Ns['Comp']`, `Ns[k]`, `Ns?.Comp`) reaches this throw. The declaration metadata of the library being linked contains a type reference the linker cannot reduce to a static dotted name.","triggerScenarios":"Linking ɵɵngDeclareDirective/Component/Injectable metadata whose entity slot (e.g. `type`) is a computed member expression like exports['MyDir']; FESM bundles where a minifier or rewriter turned dotted access into bracket access before linking; hand-maintained partial declaration calls.","commonSituations":"ng build or the standalone @angular/compiler-cli/linker consuming a partially compiled (compilationMode 'partial') library that was aggressively post-processed; version skew where a newer library's output meets an older linker; custom bundler pipelines that rewrite member expressions.","solutions":["Recompile the library with the Angular compiler so metadata contains direct references","Stop post-emit transforms (minifiers/formatters/rewriters) that convert `a.b` into `a['b']` inside ɵɵngDeclare* calls","Align the app's @angular/compiler-cli and CLI versions with (or newer than) the library's Angular version","If the published library is unmodified, reproduce with a plain CLI build and report the issue to the library maintainer"],"exampleFix":"// before\nɵɵngDeclareDirective({ minVersion: '14.1', ngImport: core, type: exports['MyDir'], selector: '[myDir]' });\n// after\nɵɵngDeclareDirective({ minVersion: '14.1', ngImport: core, type: MyDir, selector: '[myDir]' });","handlingStrategy":"type-guard","validationCode":"import * as t from '@babel/types';\nfunction isStaticTypeRef(e: t.Expression): boolean {\n  return t.isIdentifier(e) ||\n    (t.isMemberExpression(e) && !e.computed &&\n      t.isIdentifier(e.property) && isStaticTypeRef(e.object as t.Expression));\n}\n// run over entity-valued fields (type, encapsulation, ...) before linking\nconst safe = t.isObjectExpression(typeArg) && typeArg.properties.every(\n  (p) => !t.isObjectProperty(p) || !isEntityField(p) || isStaticTypeRef(p.value as t.Expression),\n);","typeGuard":"const isStaticTypeReference = (e: t.Expression): boolean =>\n  t.isIdentifier(e) ||\n  (t.isMemberExpression(e) && !e.computed &&\n    t.isIdentifier(e.property) && isStaticTypeReference(e.object as t.Expression));","tryCatchPattern":null,"preventionTips":["Do not run rewriters that turn `a.b` into `a['b']` over partially compiled bundles before linking","Link the pristine compiler output of partially compiled libraries","Keep the app's @angular/compiler-cli at or above the library's Angular version","Add a CI build step that links every partially compiled dependency"],"tags":["angular-linker","babel","partial-compilation","type-reference","computed-property"],"backgroundTag":"angular-linker-unsupported-syntax","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}