Copy it into a local const and the problem goes away:
const email = user.email
if (!email) return
setTimeout(() => send(email), 100)
The rule is about what the compiler can prove. It keeps narrowing on a const binding inside a closure because a const cannot be reassigned, ever, so the fact you established is still true whenever the closure runs. It cannot prove anything about user.email, that is a mutable property on an object anyone holds a reference to, and between now and 100ms from now literally any code could set it to undefined, including send itself. So it throws the narrowing away at the function boundary.
The reason .map() looks inconsistent is not that map is special. In the cases that compiled you were narrowing a local const; in the cases that did not you were narrowing a property. Same rule, different subject.