Long-time JS/TS/Node programmer here. Knowing ahead of time which functions are async is a feature . It's a big neon sign that says "hey, this function call is expensive ". This is a good thing for programmers to easily see and know at the call site. If you make multiple calls with async/await in a row, the performance issues are plainly obvious at the call site. With "colorless" functions, this information is hidden…
It can be, but this fact doesn't always scale well to larger APIs over time.
If you see that a function is async, any of these could be true:
1. The function does some asynchronous work.
2. The function did some asynchronous work at some point in the past, but does no longer, but changing the signature is a breaking API change, so it still looks async.
3. The function does no asynchronous work, but it's a public API and the library maintainer thinks there is a good chance it may need to do async work in the future so made it async today to reserve the right to make that change without breaking the API.
4. The function may or may not do asynchronous work, but it's part of an interface that others are allowed to implement and the designer of the interface wants to give implementers the freedom to make their implementations async if they want.
5. The function is higher-order and wants to be able to accept callbacks that are themselves async.
There are probably others I'm forgetting.
This all sounds hypothetical but it's really not. If you maintain any widely-used long-lived package, you run into design questions like this all the time.
There is always a tension between an API consumer wanting to know what a function "really" does versus the API author wanting some abstraction so that implementation details can be changed over time without breaking users.
Asynchrony is one kind of effect or observable behavior that a user/maintainer of an API may or may not want to encapsulate, but it's not the only one. The C++ standard library documents and commits to the algorithmic complexity of most functions. Haskell function signatures pin down whether or not a function does IO. Statically typed languages pin down the types parameters must be.
Pinning down more of this stuff gives the API consumer some more information, but it's not always a pure win. It calcifies the behavior of the function in ways that can harm its evolution or interact poorly with higher-order code or polymorphism. There's no silver bullet.
Personally, I've never found "does this function suspend" to be a particularly interesting effect for a function to have to commit to and the fact that it poisons the entire callstack makes it very difficult to work with in practice.