angular: Better offline compiler error when accessing private properties

I’m submitting a …

[x] bug report => search github for a similar issue or PR before submitting

Current behavior

I think this is not intended behavior but I apologize if I’m wrong:

I’m trying to move from Just-in-Time to Ahead-of-Time compilation.

1. I’ve confirmed that the App runs without errors using Just-in-Time compilation. My main.ts is:

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

2. I clear all my app files from my production folder, but keep 3rd party libraries (eg: Angular 2, Angular 2 Material)

3. I run "node_modules/.bin/ngc" -p ./ This runs with no output to the console. I see an .ngfactory.ts file for each of my .ts components and modules. I also see a .css.shim.ts file for each of my .css that held component styles. In addition, .js and .js.map files have been transpiled and placed in the production directory

4. If I try to run the app at this point, I see 404 not found errors for all the .html files that held component templates

5. I manually move all template files (.html) to production dir and run the App. It runs fine, but it still uses Just-in-Time compilation (255 requests, including compiler.umd.js)

6. I change my main.ts to:

enableProdMode();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

On its own, this makes no difference since the new code has not been compiled. However, if I run ngc again I get lots of errors of the type:

Error at C:/path/to/notify.component.ngfactory.ts:113:41: Property 'visible' is private and only accessible within class 'NotifyComponent'
... (many more like that with lots of properties from lots of components)
Compilation failed

Is this expected when I use private properties? Must all properties be declared public for AoT compilation to work?

Expected behavior

If ngc ran without a hitch before I updated main.ts to use platformBrowser(), I expected ngc to complete successfully after the change.

Reproduction of the problem

Occurs during compilation. Try to AoT compile components with private properties after updating main.ts to use platformBrowser():

constructor(private store:StorageService){}

Please tell us about your environment:

  • Angular version: 2.0.0-rc.6
  • Browser: [all]
  • Language: [TypeScript 2.0.2]
  • Node (for AoT issues): node --version = 4.5.0 npm --version = 2.15.9

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 29 (14 by maintainers)

Commits related to this issue

Most upvoted comments

Just to clarify, for myself mostly 😃

Is allowing access to private properties from the templates planned in a future release or not on the roadmap at all?

I wondered why only certain properties must be public while other private properties are acceptable. I received an excellent explanation on Stack:

For a given component all its members (methods, properties) accessed by its template must be public in the ahead-of-time compilation scenario. This is due to the fact that a template is turned into a TS class. A generated class and a component are 2 separate classes now and you can’t access private members cross-class.

In short: you can’t access private members in your templates if you want to use ahead-of-time compilation.

pkozlowski.opensource

Yes, AoT generates code. If something is private one can not see it.

An update on this request: binding to protected members from a template will be possible in v14, thanks to #45823. The error for binding to private members remains (and will remain), but it does now point at the exact location in the original template instead of some ngfactory.ts file.

Reading both @trotyl and @chuckjaz responses I’m not sure whether v5 will allow binding to private properties in the templates or not.

I hope it will allow binding to private properties because I consider the template as part of the component and not as an external consumer. Changing a bindable property used by the template as part of a refactoring should not be treated as breaking change but since v4 forces it to be public I have to assume that someone might be using it and handle it as breaking change of the API.

That some properties can be private for bindings is a bug in the way we generate code. Eventually, we do want to allow private properties, but this requires some changes in our architecture, which we are planning to do this quarter.

@atalis It is a bug that some access to private properties are not reported as errors. Because the template is generated in a separate class it doesn’t have access to private members of the original class.

In v5 we will be changing how errors in templates are reported that will improve these error messages.

We currently generate code and then use TypeScript to validate that the code we generate type checks. However, we generate code for performance, not type checking so we lose some types and and we are forced to introduce any in places that defeats the type checker (that is, if we didn’t inject an any TypeScript would report a spurious error).

Our current plan is to change to generate factories in the transformer phase of TypeScript instead of running the factories through the type-checker and then generate a separate block of code that preserves types (but would perform badly) and map the type error reported in that block back to the part of the template that generated the error.

@atalis A bug is something violating the design.

In current implementation, it’s by design to not allow private properties, so throwing error when using private property is the correct behavior and not throwing is a bug, that’s tracked at https://github.com/angular/angular/issues/14739.

But as part of the goal in v5 (or beyond), they want to re-design code generation mechanism. After that, allowing private properties will be the expected behavior.