Although mxthevs offered a valid solution, I’d like to add a more thorough explanation because I get this question very often (especially from rescript beginners).
The difference between the two signatures lies in the “perspective”.
When you type a function in the implementation: (let f = (~a: option<int>=?) => ...) you specify the types, as the function from the “inside” would perceive the given arguments. Inside the function you need to be able to differentiate, if the argument was given or not, so there is no way around option.
On the other hand, if you specify the signature in a module-type or a resi-file, this is how the function is seen from the “outside”. Therefore, the caller doesn’t need to know or handle any option type. The only thing relevant from the “outside” is, that I may or may not pass an argument of a specific type to the function.
In the same manner it’s also possible and sometimes recommended to use more abstract/generic types in the interface vs the actual implementation, to hide complexity and provide abstractions.