Consider the dual of this, #9757, where someone didn't want an error even when the variable was initialized with a reference to itself.
We could special-case IIFEs to be considered inlined for the purposes of flow analysis, but in general we can't tell whether a given function expression executes "now" or "later", so that'd just be a patch, but it might be one worth making.
IIFEs are a very common pattern, and additionally they are distinguishable on a syntactic level. It would be a great boon for flow analysis to consider them in the special way, however limited this exception may be. But like you said, not being able to tell when a function expression gets invoked is a great limitation, and might even step into the realm of escape analysis.
IIFEs are a very common pattern [....] It would be a great boon for flow analysis to consider them in the special way
#8849 already implements this, so it's surprising that it doesn't catch use before declaration. Consider the same example but with a union type for x, and another identical IIFE just after the assignment:
consty=(()=>x)();// x is string|number, due to #8849 TS *knows* it hasn't been assigned// when the IIFE runs (although unassigned consts can't exist!)constx: string|number=3;constz=(()=>x)();// x is number, due to #8849 TS *knows* it must// be a number when the IIFE runs
This shows that the compiler has treated the IIFEs as part of the surrounding control flow for the purposes of narrowing, but doesn't appear to recognise use before declaration of x.