If you take a close look at the code for the previous UserSettings example component, you may notice a weird exclamation mark:
@Inject("username") username!: string; // definite assignment assertion
Now, what is it and why did we need it?
As the official TypeScript documentation (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions) states, definite assignment assertions can be used to tell the compiler that variables will indeed be assigned, even if TypeScript can't determine this on its own.
The definite assignment assertion is used through the ! character, and is defined after a property or variable declaration.
If we consider the preceding code, at compile time, the type checker cannot possibly know that Vue's dependency injection system is going to provide the field's value after the object's construction.
From the type checker's point of view, once it is told that the value is not defined through an initializer or via a constructor, then the value is considered as not being properly initialized at construction time. Because of this, the compiler considers that the property could be undefined, which is not compliant with the defined type (at least in strict mode).
One way to fix this issue would be to change the type of the username field to string | null | undefined, but this is clearly not the best approach to take. We don't actually want our dependency to be null or undefined, and we don't want to be able to set it to such a value inadvertently.
Obviously, the better answer here is to use a definite assignment assertion, just like we did, since it allows the value to not be defined immediately at construction time, while still preventing us from intentionally setting the value to null or undefined, which is nice.
Of course, this workaround still leaves us with weaker type safety since any misconfiguration of the dependency injection could lead to errors that cannot be caught at compile time. These can only be caught at runtime.
If Vue had support for constructor injection like Angular does, then we wouldn't have this issue. We could check for the availability of our dependencies right away and we also wouldn't need to use this TypeScript feature.