RC0: TypeScript 'private' vs. 'public' keyword


#1

Hello,

first of all, thank you Ionic team for the amazing work you are doing. We’ve been really looking forward to this update.

I would like to ask about update step 29 from the changelog:

Change any uses of the private TypeScript keyword to public.

  1. Could someone please explain to me reasons for this change?
  2. And does this mean I can’t declare any class members private?

Cheers, Filip


Using "this" with html button "(click)"
#2

I opened a related issue https://github.com/driftyco/ionic-conference-app/issues/248, if someone can answer that also :slight_smile:


#3

It’s explained on blog post comments.

http://blog.ionic.io/announcing-the-ionic-2-release-candidate/


#4

Hey so just to add a bit to what Josh mentioned in the post.

In order for AoT compiler to work, it needs to map everything out ahead of time (get it?)

So when you set a property to private, AoT cannot access it. So it will introduce errors and you app will not run.

Since private/public accessors are a TS only concepts, they never really added anything to your app once it got compiled down. So it’s safe to keep everything as public.


#5

Does this only refer to properties that are referenced in templates? Say I have something like this:

@Component()
export class MyComponent {
  constructor(private _http:Http) {
  }

  methodInvokedByButtonClick(): void {
    this._http.post();
  }
}

Is that also going to be problematic?


#6

Yes this will be problematic. It needs to be both properties and injected variable references.


#7

For me, that’s a deal breaker for using AoT. I started to use Typescript because of these functionalities. Making everything public because of compilation makes me uneasy.
Is it as easy as modifying the prod file to disable AoT or is there something that needs to be done in the build (config) as well?


#8

Just wondering, Isn’t it possible for angular team to have some pre-AoT step to automatically convert everything to public OR just ignore the accessors as it’s only TS concept? Using public/private accessors in TS prevents a lot of unintentional mistakes.


#9

I’m pretty sure this issue will be tackled at some point. But until then I’d like to disable AoT


#10

Perhaps I have not yet banged into the teeth of this issue, but I have an app using the private members in the way I described upthread which seems to be working OK with the output of ionic build.


#11

So you’re saying that the AoT compiler is not smart enough to do a search/replace of private to public? And now instead we have to break a well established programming paradigm instead?

As they would say in Monty Python: That is very silly


#12

same problematic for protected?


#13

According to pkozlowski-opensource’s comment in this SO thread, this issue only applies to properties that are accessed from templates. That seems intuitive to me, but I’m wary of contradicting @mhartington.


#14

Yeah, sorry I should have been a bit more clear in thing. The way Pawel describes it is much better.

So if it needs to be accessible to the template, it needs to be public.

We recommend just using public to avoid edge cases. Plus, outside of Typescript, public/private don’t really have any meaning.

@larssn in regards to AoT being “smart enough”, the compiler only knows what you tell it, like every other compiler. If you tell it to not too look at module A, but then require module A later on…well how is it supposed to know what to do?


#15

Yeah but we’re talking about access modifiers. If the rule is: “private modifiers must not exist”, then clearly just deleting all private modifers prior to compiling isn’t some ridiculous notion? :slight_smile:

And access modifiers are valuable in how to help guide in using API’s and interfaces. I don’t want the interface of all my classes to be public, as certain methods might be for internal use only. I want my API’s to be simple and easy to understand, and access modifiers help in that aspect.


#16

Again…read the description…

Because the template becomes a class itself, anything that it needs to access need to be public. If you want to keep a private method that is only used internally to that component, go for it, keep it private. But if for some reason it needs to be exposed to the template(Class), it needs to be public.


#17

Not to beat a dead horse, but this is an important distinction to make, so that the entire concept of encapsulation isn’t lost in Typescript. Yes, it may only be a “compile-time” restriction, but it’s there so that we can take advantage of encapsulation in a declarative way; it’s a very nice feature :slight_smile: Glad to hear that we don’t have to expose everything everywhere though; template only exposure makes sense.

Thanks for the clarification!


#18

Hey Mike! Here’s a PR for making the migration steps clearer: https://github.com/driftyco/ionic/pull/8364


#19

I think TypeScript should have compiled the private variables in a different way.

class Greeter {
    private greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

should be compiled to

var Greeter = (function () {
    function Greeter(message) {
        this.___greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.___greeting;
    };
    return Greeter;
}());

So any access to greeting member will fail in js .


#20

Only member functions and variables that are used in the HTML template need to be made public. The rest can remain private. You also must make any variables declared via @Input or @Output or @ViewChild public. The good news is that if you forget to make any of these public, when you run npm run build in the home directory of a project based on a stock project started with ionic start --v2 then you will get a compiler complaint about the variable being private and you can change those one by one until all your complaints go away.


Cannot find main.js ios build