We have a problem with promises
The real confusion here is dynamic typing. It's weird that the parameter to .then() can return any value, but if it's a promise there's special behavior. And for no good reason either    p.then(r => r + 5);

Is just a bit of sugar for    p.then(r => Promise.resolve(r + 5));

And then the type signatures are easy to reason about. The dynamic typing also risks introducing hard to find bugs. Suppose you have an heterogeneous array `things` which might contain numbers and promises which will resolve to numbers.    p.then(r => things[r])
     .then(thing => selectedThings.push(thing));

You might intend `selectedThings` to also contain either numbers or promises that resolve to numbers, ordered deterministically as a function of `p`, but instead it will contain only numbers and its order is nondeterministic (it depends on `p` and all of the promise members of `things` that `p` ever signals).