docs: add a style recommendation for initializing inputs (#40698)

This practice is to better align with `strictPropertyInitialization`
which is coming by default with strict mode in v12.

PR Close #40698
This commit is contained in:
mgechev 2021-02-03 18:49:13 -08:00 committed by Joey Perrott
parent 980f6a4958
commit 72a00dcc6b
13 changed files with 123 additions and 0 deletions

View File

@ -0,0 +1,7 @@
import { Component } from '@angular/core';
@Component({
selector: 'sg-app',
template: '<toh-hero-list></toh-hero-list>'
})
export class AppComponent { }

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { HeroComponent, HeroListComponent } from './heroes';
@NgModule({
imports: [
BrowserModule,
RouterModule.forChild([{ path: '05-18', component: AppComponent }])
],
declarations: [
AppComponent,
HeroComponent,
HeroListComponent
],
exports: [AppComponent]
})
export class AppModule {}

View File

@ -0,0 +1,24 @@
import { Component } from '@angular/core';
import { Hero } from '../shared/hero.model';
@Component({
selector: 'toh-hero-list',
template: `
<section>
Our list of heroes:
<toh-hero *ngFor="let hero of heroes">
</toh-hero>
Total powers: {{totalPowers}}<br>
Average power: {{avgPower}}
</section>
`
})
export class HeroListComponent {
heroes: Hero[] = [];
totalPowers = 1;
get avgPower() {
return this.totalPowers / this.heroes.length;
}
}

View File

@ -0,0 +1 @@
export * from './hero-list.component';

View File

@ -0,0 +1,15 @@
import { Component, Input } from '@angular/core';
// #docregion example
@Component({
selector: 'toh-hero',
template: `...`
})
export class HeroComponent {
// The exclamation mark suppresses errors that a property is
// not initialized.
// Ignoring this enforcement can prevent the type checker
// from finding potential issues.
@Input() id!: string;
}
// #enddocregion example

View File

@ -0,0 +1,17 @@
import { Component, Input } from '@angular/core';
// #docregion example
@Component({
selector: 'toh-hero',
template: `...`
})
export class HeroComponent {
@Input() id?: string;
process() {
if (this.id) {
// ...
}
}
}
// #enddocregion example

View File

@ -0,0 +1,11 @@
import { Component, Input } from '@angular/core';
// #docregion example
@Component({
selector: 'toh-hero',
template: `...`
})
export class HeroComponent {
@Input() id = 'default_id';
}
// #enddocregion example

View File

@ -0,0 +1 @@
export * from './hero.component';

View File

@ -0,0 +1,3 @@
export * from './hero';
export * from './hero-list';
export * from './shared';

View File

@ -0,0 +1,4 @@
export interface Hero {
id: number;
name: string;
}

View File

@ -0,0 +1 @@
export * from './hero.model';

View File

@ -0,0 +1,2 @@
export * from './heroes';
export * from './app.component';

View File

@ -3381,6 +3381,23 @@ helps instantly identify which members of the component serve which purpose.
<a href="#toc">Back to top</a>
### Initialize inputs
#### Style 05-18
TypeScript's `--strictPropertyInitialization` compiler option ensures that a class initializes its properties during construction. When enabled, this option causes the TypeScript compiler to report an error if the class does not set a value to any property that is not explicitly marked as optional.
By design, Angular treats all `@Input` properties as optional. When possible, you should satisfy `--strictPropertyInitialization` by providing a default value.
<code-example path="styleguide/src/05-18/app/heroes/hero/hero.component.ts" region="example" header="app/heroes/hero/hero.component.ts"></code-example>
If the property is hard to construct a default value for, use `?` to explicitly mark the property as optional.
<code-example path="styleguide/src/05-18/app/heroes/hero/hero.component.optional.ts" region="example" header="app/heroes/hero/hero.component.ts"></code-example>
You may want to have a required `@Input` field, meaning all your component users are required to pass that attribute. In such cases, use a default value. Just suppressing the TypeScript error with `!` is insufficient and should be avoided because it will prevent the type checker ensure the input value is provided.
<code-example path="styleguide/src/05-18/app/heroes/hero/hero.component.avoid.ts" region="example" header="app/heroes/hero/hero.component.ts"></code-example>
## Directives