Just something to be aware of: type parameters in the implementation signature are actually unification variables, meaning they will unify with (become) the first type that the compiler infers from the function body. If you want real type parameters locally abstract types are one way to do it but I’d say the more idiomatic way would be to not annotate the implementation, instead to write an interface file with the type signature of the function:
let noneIfEmptyString: (string, string => 'a) => option<'a>