Komunikat możemy otrzymać Property has no initializer and is not definitely assigned in the constructor
podczas dodawania konfiguracji w tsconfig.json
pliku, aby projekt Angular był skompilowany w trybie ścisłym:
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"noImplicitThis": true,
"alwaysStrict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
Rzeczywiście, kompilator następnie skarży się, że zmienna składowa nie jest zdefiniowana przed użyciem.
Na przykład zmiennej składowej, która nie jest zdefiniowana w czasie kompilacji, zmienna składowa mająca @Input
dyrektywę:
@Input() userId: string;
Moglibyśmy wyciszyć kompilator, stwierdzając, że zmienna może być opcjonalna:
@Input() userId?: string;
Ale wtedy musielibyśmy poradzić sobie z przypadkiem niezdefiniowanej zmiennej i zaśmiecać kod źródłowy takimi instrukcjami:
if (this.userId) {
} else {
}
Zamiast tego, wiedząc, że wartość tej zmiennej składowej zostanie zdefiniowana w czasie, to znaczy zostanie zdefiniowana przed użyciem, możemy powiedzieć kompilatorowi, aby nie martwił się, że nie zostanie zdefiniowana.
Sposobem na przekazanie tego kompilatorowi jest dodanie ! definite assignment assertion
operatora, na przykład:
@Input() userId!: string;
Teraz kompilator rozumie, że ta zmienna, chociaż nie została zdefiniowana w czasie kompilacji, powinna zostać zdefiniowana w czasie wykonywania i w czasie, zanim zostanie użyta.
Teraz aplikacja musi upewnić się, że ta zmienna została zdefiniowana przed użyciem.
Jako dodatkowe zabezpieczenie możemy zapewnić, że zmienna jest definiowana, zanim jej użyjemy.
Możemy stwierdzić, że zmienna jest zdefiniowana, to znaczy, że wymagane powiązanie wejściowe zostało faktycznie dostarczone przez kontekst wywołujący:
private assertInputsProvided(): void {
if (!this.userId) {
throw (new Error("The required input [userId] was not provided"));
}
}
public ngOnInit(): void {
this.assertInputsProvided();
}
Wiedząc, że zmienna została zdefiniowana, można jej teraz użyć:
ngOnChanges() {
this.userService.get(this.userId)
.subscribe(user => {
this.update(user.confirmedEmail);
});
}
Należy zauważyć, że ngOnInit
metoda jest wywoływana po próbie powiązań wejściowych, nawet jeśli żadne rzeczywiste dane wejściowe nie zostały dostarczone do powiązań.
Podczas gdy ngOnChanges
metoda jest wywoływana po próbie powiązań wejściowych i tylko wtedy, gdy rzeczywiste dane wejściowe zostały dostarczone do powiązań.