Optional arguments are implemented in a specific way:
From outside of the function, they look like arguments of the actual type (except in one case where you explicitly pass in an option value directly)
From inside the function, they look like values of type option<theType>.
What this practically means is if you have a function e.g. let f: (~arg: int=?, unit) => int, then you should normally call it with an actual int value, e.g. f(~arg=1, ()).
Note that in ReScript you don’t actually need to annotate the type. You could just write
let f = (~arg=?, ()) =>
switch arg {
| Some(x) => x + 1
| None => -1
}
And this whole thing is a non-issue as the typechecker just figures out the correct type.
If you want type signatures for documentation, you can always use interface files.