Generics & render props

Hi! I’m new to ReScript and am learning by replacing a Js library i’ve written with rescript.

  1. it’s a react component
  2. it uses render props
  3. it takes an array of items in props which can be any shape, the component itself doesn’t care (the array must have items of the same type, but the component doesn’t rely on that type being anything in particular)

I’m having a problem with #3 - Rescript seems to infer array<int> when I expect it to use array<'item>

What am I getting wrong?

Here’s a playground with the code

Hi @VinSpee.

I guess you should be passing current to isLastChunk function on line 69.

fixed playground link

Also I think we can use a tuple instead of an array for the state. Then Belt can be removed and no need to switch over option to extract current[0]

Thank you! That worked, and switching to a tuple is a great call, thanks.

Another question, what’s the best way to model onEnd? Its a callback passed in by the consumer, and in TS I’d model it as an optional (any) => any. What’s a better way?

Thanks again!

The onEnd could be an optional labelled argument.

 @react.component
  let make = (
    ~by=1,
    ~replace=false,
    ~items: array<'item>,
    ~onEnd=?,
    ~children: children<'item>,
  ) => {
    let isLastChunk = end => {
      let isLast = end >= Array.length(items) - 1

      if isLast {
        switch onEnd {
        | Some(onEnd) => onEnd()
        | None => ()
        }
      }
      isLast
    }
       }

Docs for optional prop .

Thanks, I’m not sure if that’s what I’m after, for example, there might be consumers which provide different functions:

example:

let onEnd = JestJs.inferred_fn

where the signature for JestJS.inferred_fn is

unit => Jest.MockJs.fn<
  (. 'a) => Js.undefined<'b>,
  'a,
  Js.undefined<'b>,
>

This results in the following error:

This has type:

"onEnd": option<unit => Jest.MockJs.fn<(. 'a) => 
  Js.undefined<'b>, 'a, Js.undefined<'b>>,
>,

Somewhere wanted:

"onEnd": option<unit => unit>,

Types for method onEnd are incompatible

essentially the type of onEnd doesn’t matter to me as long as it’s a function. How can I model that?

I guess this can not be done in statically typed languages.

let onEnd = () => {
    let a = JestJs.inferred_fn()
    /*
     Do your stuff here
    */
    ()
}

Would this work for you?

In this case, you can use the ignore function to “eat” the output and return unit. I.e., something like

let onEnd = ...
let x = ...
let onEnd = () => ignore(onEnd(x))

This should mean the caller provides a function of type unit => unit, which fit into the type.

My experience is that it is usually better to define the narrowest possible interface and have the caller adapt to it rather than having the callee handle multiple types of different possible inputs, where applicable.

Thanks!

I’ll follow advice and make the type stricter ((unit => unit)).