Most of you are probably familiar with a very simple use case from your projects.
Imagine you have a utility class or function that looks like this:
type Options = {
foo?: string
};
class Something {
static get defaultOptions(): Options {
return {
foo: "bar"
};
}
options: Options;
constructor(options: Options) {
this.options = Object.assign({}, options, Something.defaultOptions);
}
toString(): string {
return `some thing: ${this.options.foo}`;
}
}
This is just a basic example, but the point is clear - in the toString method, we can be certain that options.foo exists and will be a string.
However, Flow complains because it assumes it understands the call stack, when in fact it does not take the Object.assign statement into consideration.
So, how do we solve this issue?
We would like to avoid:
- Adding getter methods for each option.
- Adding a second type that is complete and concrete and used as a hint for the property.
At this stage, some may find flowtype less than ideal.
UPDATE
In this example, Flow will throw an error message similar to this:
Cannot coerce this.options.foo to string because undefined [1] should not be coerced.
[1] 13│ foo?: string,
:
47│ }
48│
49│ get toString(): string {
50│ return `some thing: ${this.options.foo}`;
51│ }
52│