why TS is complaining that 'data.st' is possibly 'undefined'.
in this code, even its inside the if condition.
interface Data {
st?: number;
}
let events = [{id: 1, st: 123}, {id: 2, st: 465}];
function test(data: Data) {
if (data.st) {
events = events.filter(
(ce) => ce.st >= data.st, // 'data.st' is possibly 'undefined'.
);
}
}
here is the playground.
CodePudding user response:
You need to create a ref
to the data
that you want to use and check that.
Something similar to this:
function test(data: Data) {
const st = data.st;
if (st) {
events = events.filter(
(ce) => ce.st >= st
);
}
}
They main reason why this TS
cannot narrow here is because is actually unsound
.
You are passing a callback to events.filter
and there is no guarantee that your callback is gonna get executed right away. There is no way (at least to my knowledge) to signal that a function will execute the callbacks provided in the same execution run. In this case we know that Array.filter
does this, but from TS
point of view there is no guarantee of this.
The second reason why this doesn't work is that TS
cannot properly track all the references to data
to figure out is some other piece of code could change data.ts
between the time of the check and the time of the execution callback.
It can actually figure this out if you declare it as const
and then narrow it.
The behaviour regarding callbacks can also be noticed in this case:
function test(data: Data) {
let st = data.st;
if (st) {
events = events.filter(
(ce) => ce.st >= st
);
}
}
You are still gonna get the same error now. The main reason is the callback call. If you check the st
type before the callback you'll see that it got narrowed to number
, but inside the callback it gets widened to number | undefined
.
You can check the second example here