Repository navigation
compiler-cli: lowering_expression transformer does not handle forwardRef like function #20216
Description
Activity
@tbosch I think its an edge case of microsoft/TypeScript#17384 you didn't handle
Also, using TS 2.5.3 and 2.6.1 did not solve the problem.
Another update to help identify the source:
export class MyClass { @MyPropDecorator(() => 15) prop: string; }
It doesn't have to be a custom type, even intrinsic types will fail.
Reacted by ALDINEY MENDES SANTOS- added a commit that references this issue
on Nov 6, 2017 OK, for now, if by any change someone is interested, this is a working, monkey patching, workaround:
/** * This module will patch the `@angular/compiler-cli` so it will correctly lower expression to declarations in decorators. * See https://github.com/angular/angular/issues/20216 */ import * as ts from 'typescript'; import '@angular/compiler-cli'; const lowerExpressions = require('@angular/compiler-cli/src/transformers/lower_expressions'); function touchNode(node: ts.Node) { if (!node.parent) { const original: ts.Node = <any> ts.getOriginalNode(node); if (original !== node && original.parent) { node.parent = original.parent; ts.forEachChild(node, touchNode) } } } const getExpressionLoweringTransformFactory = lowerExpressions.getExpressionLoweringTransformFactory; lowerExpressions.getExpressionLoweringTransformFactory = function(requestsMap, program) { const fn = getExpressionLoweringTransformFactory(requestsMap, program); return context => sourceFile => { const result = fn(context)(sourceFile); if (result !== sourceFile) { ts.forEachChild(result, touchNode) } return result; }; };
just import this file in the top of your webpack config module, or if you use
ngcinvoke it from a local file.Reacted by Kirill Groshkov- addedarea: coreIssues related to the framework runtimeIssues related to the framework runtime
on Nov 6, 2017 waiting for the fix..
Any tips on how to integrate this fix into an
@angular/cli@1.5.0project without having tong eject?Reacted by Philipp Denzler, Karim Saadi, Janne Julkunen, Phil Jones, ALDINEY MENDES SANTOS, dmostert, Matthew Salsamendi, Andrey Klimov and Kirill Groshkovcreate a local
ngexecutable that acts as a pass-through.
It will run the workaround first, then pass control to the original ng script.Assuming the following file is in the root of the project:
Filename: ng
#!/usr/bin/env node /// WORKAROUND HERE require('node_modules/.bin/ng');
Did not test it, but should work.
Maybe some modifications based on OS.You can also add it to your package.json scripts
Reacted by el-davotypestack/class-transformer#108
export function serializeType<T>(object: T) { return function () { return object; } } export class CatalogItem { id: string; @Type(serializeType(CatalogCategory)) category?: CatalogCategory = null; @Type(serializeType(PackingVariant)) packing: PackingVariant; price: string = null; }Reacted by Yosip CurielReacted by Yosip CurielI had the same issue with:
Angular CLI 1.6.1
Typescript 2.4.2
Angular 5.0.2Found a solution by changing typescript.js for now.
Replace all the function
function nodeCanBeDecorated(node)
with the following codefunction nodeCanBeDecorated(node) { switch (node.kind) { case 229 /* ClassDeclaration */: // classes are valid targets return true; case 149 /* PropertyDeclaration */: // property declarations are valid if their parent is a class declaration. // return node.parent.kind === 229 /* ClassDeclaration */; return (node.parent && node.parent.kind === 229) || (node.original && node.original.parent && node.original.parent.kind === 229); case 153 /* GetAccessor */: case 154 /* SetAccessor */: case 151 /* MethodDeclaration */: // if this method has a body and its parent is a class declaration, this is a valid target. return node.body !== undefined && // && node.parent.kind === 229 /* ClassDeclaration */; (node.parent && node.parent.kind === 229) || (node.original && node.original.parent && node.original.parent.kind === 229); case 146 /* Parameter */: // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target; // return node.parent.body !== undefined // && (node.parent.kind === 152 /* Constructor */ // || node.parent.kind === 151 /* MethodDeclaration */ // || node.parent.kind === 154 /* SetAccessor */) // && node.parent.parent.kind === 229 /* ClassDeclaration */; var parent = node.parent || (node.original && node.original.parent); return parent && parent.body !== undefined && (parent.kind === 152 || parent.kind === 151 || parent.kind === 154) && parent.parent.kind === 229; } return false; }Which comes from here, if you compile typescript:
shlomiassaf/TypeScript@7017fa2I want to share my workaround that I put together after reading other advices here and there. It's patching an
ngscript from@angular/cli@1.6.4(current version at the moment of writing). Because of that it prevents updating@angular/cli, so be prepared.- Put a patched copy of
ngsomewhere in your repo. You can grab patched version from here:
https://github.com/kirillgroshkov/angular-cli/blob/18f14d71bc5d73dba488f8fc1d08fd46d1d885f1/packages/%40angular/cli/bin/ng
Here's what changed, compared to the original file: https://github.com/kirillgroshkov/angular-cli/commit/18f14d71bc5d73dba488f8fc1d08fd46d1d885f1
- Add a
postinstallscript in yourpackage.jsonthat will run every time after you donpm install(oryarn install) and copy/overwritengfrom your location tonode_modules/@angular/cli/bin/ng.
"postinstall": "echo 'patching @angular/cli' & cp ./other/ng ./node_modules/@angular/cli/bin"- Run your build as normal, you should see console.log message "!!! using patched @angular/cli".
- Profit
- Put a patched copy of
@kirillgroshkov Your solution cannot be applied in my context (@angular 5.0.3)
$ ls node_modules/@angular common/ compiler/ compiler-cli/ core/ forms/ http/ platform-browser/ platform-browser-dynamic/ $ ls node_modules/@angular/compiler-cli index.d.ts index.js index.js.map ngtools2.d.ts ngtools2.js ngtools2.js.map package.json README.md src/
any hints?
@daixtrose My solution is when
@angular/cliis used in the project. Seems you you don't use it (cause I can't see it in node_modules), then how do you compile your angular project? Anyway, if you dig deeper, you'll find what lines you need to add to your compiler script to make it work, good luck!ps: Lines are there, between 4 and 29:
https://github.com/kirillgroshkov/angular-cli/blob/18f14d71bc5d73dba488f8fc1d08fd46d1d885f1/packages/%40angular/cli/bin/ngAlso not working in Angular
class Test { @Transform( (value) => plainToClass(ApplicationData, JSON.parse(value)), { toClassOnly: true } ) @Transform( (value) => JSON.stringify(classToPlain(value)), { toPlainOnly: true } ) data: ApplicationData; }
- addedarea: compilerIssues related to `ngc`, Angular's template compilerIssues related to `ngc`, Angular's template compilerand removedarea: coreIssues related to the framework runtimeIssues related to the framework runtime
on Mar 15, 2020 Apparently, this started working from Angular CLI 1.7 onwards, so somehow the CLI was involved. I can't reproduce this in newer versions of Angular (or even with Angular 5.0.0, TS 2.4.2 and CLI 1.7.0) so I'm closing as resolved.
angular-automatic-lock-bot commented
on Apr 15, 2020 More actionsThis issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.
- locked and limited conversation to collaborators
on Apr 15, 2020
SHLASSAF-M-4099:testproj shlomiassaf$ ng build --aot --build-optimizer Date: 2017-11-06T04:02:00.134Z Hash: 957bab95fbd81c3b3b0f Time: 3658ms chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered] chunk {main} main.bundle.js, main.bundle.js.map (main) 303 bytes [initial] [rendered] chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 323 bytes [initial] [rendered] chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 11.3 kB [initial] [rendered] ERROR in Error: TypeError: Cannot read property 'kind' of undefined at nodeCanBeDecorated (/Users/shlomiassaf/Desktop/Cisco/personal/testproj/node_modules/typescript/lib/typescript.js:7805:35)This will work:
Being explicit won't help
BUT, being static will help:
Thanks!