4

Context

I recently upgraded to a newer version of Angular (I moved up, in three steps, from 10 to 13).

One of the upgrade steps included a dependency on a new version of typescript, which "strict" compiler mode raises an error, if a declared variable doesn't get assigned a value at initialization.

As consequence, all my components now fail the TS build process, because properties decorated as @Input() are usually not initialised.

Now I face a choice: either I turn off the strict mode (thing which I absolutely don't want to do, especially with this new feature that I find extremely useful), or I go and add an exclamative point on every single @Input() in every single component, like this

@Input() something!: SomeType;

(this is a way to tell the TS compiler to ignore the uninitialised property)

Question

I would like to know what is Angular's official policy on this topic, whether there are any accepted best practices.

My thoughts

The core of the problem is that @Input() properties on an Angular component aren't meant to be initialised in the same way as regular properties, since their value comes from the parent component in the template. So, I'd expect them to be treated differently in an Angular context.

I would like to find a way to "delegate" the responsibility, from Typescript to Angular, of this specific strict check.

Ideally, I would like to bypass the Typescript strict check, and mark instead each input as compulsory / optional as part of the specific TS build process for Angular: Angular would look at each instance of that component, and, based on the context where the component is called in the parent HTML template, it would decide whether raising a compiler error

For example, if my component contains two inputs like these

@Input() compulsoryProp: string;
@Input() optionalProp: string = 'default value';

the new Typescript compiler would fail on compulsoryProp, and it would try to force me to turn it into something like

@Input() compulsoryProp: string | undefined = undefined;

This is what I don't want to do. I would like Angular to figure this out on its own, and raise a compiler error ONLY if I am calling the component, in a parent template, without passing the property compulsoryProp.

Apologies if this question has already been answered elsewhere. I was surprised to find very few discussions about this topic: the principal thing that comes up on Google results is this other question, but the answer is not satisfactory

Adriano di Lauro
  • 469
  • 4
  • 10
  • 1
    TS has no way of seeing what's being passed from parent to child. It is always undefined. Even if you are sending value from parent `[mVal]="value"`. TS can get passed values only during compile time to assess type checking. This is not a problem with Angular rather how TS and linting works. Your offered solutions are good ones - either that or perhaps writing a rule to the linter for this case. At least, that's my understanding of it. – Joosep Parts Feb 16 '22 at 04:48
  • Given that I have no answer myself, I think that the exclamation point might be the right answer, not even a workaround but the way it's supposed to be used. This is a great excuse to learn how to use your IDE to find/replace code via regular expressions! Searching for something *like* (not debugged) `^(\s*\@Input\(.*\)\s.+[^!])(:[^=]+)$` and replacing with `$1!$2` to find @Input lines that don't contain "!:" or "=" and insert a "!" before the colon would make your job much easier. – JSmart523 Feb 16 '22 at 05:34
  • maybe this answer could help https://stackoverflow.com/questions/66168766/leaving-angular-component-input-unassigned – rome May 11 '23 at 09:36

1 Answers1

0

I agree with you that angular team should find out the some way out of this. But till that you can go with the below config options to avoid the adding an exclamative point.

Add below to two lines option by which you will still be the strict mode but it will not the error.

Notice: add this after strict mode only otherwise it will not work.

{
  ...
  "noImplicitReturns": false,
  "strictPropertyInitialization": false,
  ...
}
Deep Patel
  • 61
  • 2