How to type a high order function that takes a callback with type arguments?

Hello.
I have some code using Recoil that I want to refactor. The code I want to refactor uses useRecoilCallback and makes use of the set function provided by it in several places. I want to extract one tedious part that is just calling set in a bunch of atoms. Set, as provided by recoil is a generic function taking one type argument, and using it in the context of the callback works just fine despite I am providing different several value types to it. However, when I want to take it as argument in my own functions I am facing problems with rescript type system, which is trying to concrete the type of the type argument.

This is an extract of the code I want to write:

type setLayer('value) = (Recoil.readWrite('value), 'value => 'value) => unit;

let setLayerProperties =
    (
      ~set: setLayer('a),
      ~id,
      ~point,
      ~dimensions,
      ~rounded,
      ~frameStyle,
      ~order,
      ~videoHidden,
      (),
    ) => {
  switch (point) {
  | Some(point) => Atoms__Layer.point(id)->set(_ => Some(point)) // <- this is fine, but narrows down the type
  | None => ()
  };
  switch (dimensions) {
  | Some(dimensions) => Atoms__Layer.dimensions(id)->set(_ => dimensions) // <- This is already an error
  | None => ()
  };

As I said, in the context of Recoil.useRecoilCallback(({snapshot, set}, bla) => { .. the set function can be called with several different atoms without a problem, why is it not in my own function?

2 Likes