Opinion on data with contstuctors


#1

Is there a opinion on when to put data in the constructor vs when to just place it in the class? I know that if it has to do with DI then it should be in the constructor but for instance:

export class SomeComponent {

  text: string;

  constructor() {
    this.text = 'Hello World';
  }

}

works and so does

export class SomeComponent {

  text = 'Hello World';

  constructor() {}

}

EDIT: This also works

export class SomeComponent {

  text:string = 'Hello World';

  constructor() {}

}

#2

I have no idea if the content is a “best practice”, but someone wrote a blog post on this topic:


And some more on SO:

So you should use constructor() to setup Dependency Injection and not much else. ngOnInit() is better place to “start” - it’s where/when components’ bindings are resolved.


#3

Wow yes, this is the stuff I was looking for. Thanks!


#4

Counter argument / Objection:


:wink:


#5

lol so it’s either do the initial ‘work’ inside ngOnInit or inside the constructor within the platform.ready promise. Got it, neither case shows initializing variables openly inside the class…but I assume it’s fine to do from the SO response “(actually implementing OnInit is not mandatory but considered good practice)”. And as far as defining the type goes, that is just an optional TS feature?


#6

Well, platform would also be available in ngOnInit - this might also have been an (unconscious?) choice done by some Ionic dev… As all these posts describe both works, it’s just a question of style and choice and… moon phase?


#7

You can/should initialize variables inside the constructor (which is the same as initializing them “above” the constructor) in the sense of
example: string[] = new Array<string>();
But performing computation in general is best done in ngOnInit() or ngAfterViewInit(). A big part of the reason for this in Ionic is that then the page preloads faster. So the rule of thumb is to keep the constructor as light weight as possible.


#8

I see, because typically constructor is called before ngOnInit? So it’s a chance to get the variable initialized earlier in the overall component lifecycle?


#9

Always. First you construct the page. Then, once the page is initialized, then ngOnInit() is entered. If you ensure all your variables are defined you avoid a lot of annoying Javascript undefined property errors. So it’s simpler to code pages if you make that part of your work habit. Or at least I’ve found that to be true.


#10

Others have already covered most of the ground here, but a couple additional observations:

Magical properties that are filled by the framework (@ViewChild, @Input) cannot be interacted with in the constructor. They can only be accessed from specific lifecycle events.

Of OP’s three options, I prefer #2. While it’s certainly a great habit to be typing things, in this situation TypeScript can infer from the initialization that text is of type string, and so while #3 isn’t necessarily bad, it would make a reader wonder whether something unusual is going on. #1 I do think is (relatively) bad, because it forces a reader to look in two separate places to see type and initial value, and also enables forgetting to set the initial value at all if it’s not done while declaring the property.


#11

would

text:string = 'hello world'

be evaluated at the same time as

text:string
constructor() { this.text = 'hello world' }

#12

Yes. Here’s my typical fruits array I use in my sandbox project:

class HomePage {
  fruits = ['apple', 'banana', 'cherry'];

  constructor(public navCtrl: NavController) {
  }
}

It transpiles to this:

var HomePage = (function () {
    function HomePage(navCtrl) {
        this.navCtrl = navCtrl;
        this.fruits = ['apple', 'banana', 'cherry'];
    }

#13

Good point to just check what it transpiles to.

What’s your workflow to check this? So @codemax999 can replicate with his 3 options maybe…


#14

Open up www/build/main.js, C-f “fruits”.


#15

lol better change my test from ‘text’