I have a definition of type Payment
like this:
type Payment = {
sid: string | null;
}
function doit(payments: Payment[]) {
payments.forEach(payment => {
if (
payment.sid
) {
// this is good
const sid: string = payment.sid;
(async () => {
// this fails
const sid: string = payment.sid;
})()
}
});
}
The problem above is that const sid
is seen as being possibly null. Now I know I can move the gaurd into that IIFE, however I know for a fact it's going to be truthy.
CodePudding user response:
This is currently a missing feature of TypeScript, see microsoft/TypeScript#30625.
In general the TypeScript compiler does not have the resources to do proper control flow analysis on closed-over values across function boundaries. See microsoft/TypeScript#9998 for a full discussion of this. For most situations, the type checker does not track when a function will be called, so it doesn't know if any narrowings that occur outside the function body will be in effect inside the function body. Any such narrowings are effectively reset inside the function. Even if a human being could look at the code and see that the values should be narrowed, the compiler does not do this.
Now, for immediately invoked function expressions (IIFEs), in particular, the compiler does "inline" the function body in terms of control flow analysis. This was implemented in microsoft/TypeScript#8849. If you remove the async
keyword, the compiler recognizes that the function body is in the same narrowing state as the outer scope, and so payment.sid
is still non-null.
Unfortunately this was not done for immediately invoked async
functions. In general such functions tend to have await
in them, and once you pass an await
then the compiler cannot be sure when it will be run and whether previously narrowed values are still narrowed.
In the particular case of the part of an immediately invoked async
function before the first await
, it would be possible for the compiler to keep the narrowing. It just isn't implemented. As I mentioned at the start, microsoft/TypeScript#30625 is an open issue asking for this. But there doesn't seem to be much community support for or awareness of it. You could go there and give it a