The following is an example that reproduces the problem:
type F = () => number;
type R = {
[ x: string ]: R | F | undefined
}
const isFunc = <T extends (...args: any[]) => any>(maybe:unknown) : maybe is T => typeof maybe === "function";
const check = (i: R) => {
let tmp:R = i;
let curr = tmp["something"];
if( isFunc<F>(curr) ) return;
curr // R | undefined, expected
tmp = curr || (curr = {}); //ok, expected
tmp = curr ||= {}; //Index signature is missing in type 'F'
};
As you can see, after the type guard, curr
is correctly narrowed to R | undefined
. After that, I am reassigning tmp
to curr
and defaulting the latter to an empty object should it be missing.
Now, if the A || A = B
approach is used, curr
on the left side of the logical OR is properly narrowed to R | undefined
. However, if I use the logical OR assignment to make the intent clearer, curr
is inferred as R | F | undefined
. This obviously results in an error, since F
is not assignable to R
.
The question is - what would be the reason for curr
to be losing the narrowing in the second case?