Here is a reduced code snippet to illustrate the issue:
type A = {
b?: number | undefined;
}
const a: NonNullable<Required<A>> = {
b: 0,
};
a.b++;
Currently, the a.b++
operation produces this TSC error:
TS18048: 'a.b' is possibly 'undefined'.
More descriptive error:
return new TSError(diagnosticText, diagnosticCodes, diagnostics);
^
TSError: ⨯ Unable to compile TypeScript:
project/src/test.ts:9:1 - error TS2532: Object is possibly 'undefined'.
9 a.b++;
~~~
It seems to only happen with the exactOptionalPropertyTypes
option enabled.
My assumption was that the combination of Required
and NonNullable
should yield a type in which b
should always be defined, but it doesn't seem to be the case.
Is it possible to achieve this?
The NonNullable
in your code doesn't do what you're expecting: It would remove null
and undefined
from A
itself if it were a union containing them, but it doesn't do anything to A
's properties.
But you can create a mapped type to do it:
type NoNullableProperties<T> = {
[Key in keyof T]: NonNullable<T[Key]>;
};
Then this works:
const a: NoNullableProperties<Required<A>> = {
b: 0,
};
a.b++;
console.log(a.b);