Does this empty type do anything?

In the Apollo Client bindings, there’s a type defined as this:

module FieldMergeFunction = {
  module Js_ = {
    type t
  }
  type t = Js_.t
}

Does the Js_ do some compiler tricks I can’t find, or is this type worthless- basically a placeholder for something to be implemented in the future?

That’s an abstract type. Its purpose is to be a type which is defined in terms of the functions that use it, not in terms of its contents. Its utility will become clear from functions that use it in some operations. It’s a common technique in bindings. Although I don’t know why there’s a nested module Js_ as well. It seems redundant. You’d have to ask the binding author.

Aah, ok. Is there any good strategy for finding out more about it? The compiler’s not helping me that much. I tried giving it a garbage value to see what’s expected, but that doesn’t give me more than the type:

let fieldMergeFunction: ApolloClient__Cache_InMemory_Policies_FieldPolicy.FieldMergeFunction.t = 42


[ReScript] [E] This has type: int
Somewhere wanted:
  ApolloClient__Cache_InMemory_Policies_FieldPolicy.FieldMergeFunction.t
    (defined as
    ApolloClient__Cache_InMemory_Policies_FieldPolicy.FieldMergeFunction.Js_.t)

Digging through the codebase there’s only one other reference to this type, which doesn’t shed any more light onto what’s expected. I’m stumped as to how the compiler can confidently say I’m using the type wrong, while there doesn’t seem to be anything in the code saying what’s right.

There should be functions that produce values of this type. The compiler will make sure that the value comes from such a function, which is enough to make sure the code is correct even though the content of the value is not defined.

If there’re no such functions, it can be because of many reasons:

  • This code was generated, and under some conditions functions are not generated because they are not needed or something.
  • They’re defined in some other library.
  • The bindings are simply incomplete.
1 Like

Ok, makes sense. I suspect this binding’s incomplete. I’ll check with the maintainers.

Thanks all!