Personally, I’d prefer typeof, because it would also work for non-async fns – including fns that return impl Trait, fixing the inability to name their return type, or indeed any other fn whose type you want to name, which would allow impling arbitrary traits for specific fns.
typeof would also have a variety of hackier use cases, especially around macros, which seems to be the source of some opposition to having it in the language. But for one thing, what’s wrong with hacks? 
For another, I think it’ll be possible eventually to implement at least a subset of typeof as a macro using const generics (once const generics supports arbitrary types). Something like this:
trait Foo<T, const val: T> {
type T;
}
impl<T, const val: T> Foo<T, val> for () {
type T = T;
}
macro_rules! type_of {
($e:expr) => { <() as Foo<_, {$e}>>::Output }
}
That wouldn’t work in all cases (only for constant expressions), but the point is, eschewing typeof won’t stop hacks, just make them even hackier. Moreover, if there are currently any implementation obstacles to making typeof work (I am not sure), const generics will probably have to deal with the same issues. (FWIW, I know of at least one issue that currently affects expressions written in array lengths, and probably has to be solved for const generics, but probably wouldn’t affect typeof.)
So I think we may as well have typeof, considering how handy it’s turned out to be in other languages; and then we may as well use it for this.