Why can’t the compiler infer the type of photo from this block? If I remove : Fragments.Photo.t I get errors for each property: The record field id can't be found. I feel like the compiler should be able to match the type of photos (array<Fragments.Photo.t>) with the type for the function.
Roughly speaking, the compiler searches inside modules for record field names when trying to figure out types. So if a record type is defined in another module, and that module is not ‘open’ in the current scope, it can’t find the field names, and can’t decide what the type is.
The best way to solve this is to tell it what module to look in, e.g.
Yep, that works too. It just surprises me- it feels like specifying the return type should give the compiler all it needs to infer the type of the data I’m trying to return.
Inference in ReScript doesn’t work exactly like that. The type annotation just tells the compiler, ‘first infer the type, then assert that it matches the annotated type, if it doesn’t, throw a type error’.
So the type annotation doesn’t impact the inference. There is a little bit of nuance here that I’m glossing over, but this is basically it.
Another way to think about this is the compiler needs to know what type a variable is before it can do anything with it. For example, if there are two map actions that use the same photos variable only the first will need to specify how to find the record fields. Any subsequent use will have that information already.
let keys = photos->Belt.Array.map(p => p.Fragments.Photo.id)
let images = {photos->Belt.Array.map(
({thumbnail: src, id: key}) =>
<img src key />
)->React.array}
Another way to do this is specify the type in the function argument, as you discovered, but I usually prefer the inline approach.