I recommend the paper "Complete and Easy Bidirectional Typechecking
for Higher-Rank Polymorphism" by Dunfield and Krishnaswami. It describes an easy to implement algorithm for type inference for higher ranked types that can subsume Hindley-Milner.
Your comment expanded out is what I had hoped that blogpost would have been. Thank you for posting this. It's hard to overstate how much easier bidirectional typechecking is compared to other approaches.
Implementation in Haskell: https://github.com/ollef/Bidirectional
Implementation in Javascript/Typescript (by me): https://github.com/atennapel/bidirectional.js