Question on why type inference isn't working


#1

I’m new to ReasonML and also new to typed languages (just a little Flow). I’m creating a library to learn the language and I ran into a situation where the type inference works in the “Try Now” with the types all in one file. However, in my React render function, it doesn’t work, saying ..

I would assume that if I manually type the param (completely reasonable… no pun intended), then the List.find function should infer the list elements. Am I doing something wrong or is this standard?

Example on Try Reason:

type schemaItem = { name: string, label: string };
type schemas = list(schemaItem);
let formSchema: schemas = [
  {name: "name", label: "Name"},
  {name: "age", label: "Age"},
];


Js.log(
  List.find(x => x.name == "age", formSchema)
);

Example in my code, working with type on X (simplified)

type scItem = SF_Form.schemaItem;
type schemaList = list(SF_Form.schemaItem);

let make = (~formSchema: schemaList, _children) => {
  ...component,
  render: _self => {
    let schema =
      formSchema |> List.find((x: scItem) => x.name == "firstName");
    <div>(text(schema.label))</div>
  },
};

Can not infer type scItem of x “The record field name can’t be found.”

type scItem = SF_Form.schemaItem;
type schemaList = list(SF_Form.schemaItem);

let make = (~formSchema: schemaList, _children) => {
  ...component,
  render: _self => {
    let schema =
      formSchema |> List.find(x => x.name == "firstName");
    <div>(text(schema.label))</div>
  },
};

To recap, why is the type scItem needed? couldn’t Reason infer that the type schemaList is a list of schema items and then use that information for x?


#2

Hi!

I’m not an expert either but records and fields are quite different from what you would expect in ocaml/reason. The docs don’t have much information but you may find this post (and the whole series) useful:

I’d recommend going through the whole section and article if you have the time, since they have some unintuitive behavior when coming from JS.

In summary, the x field is not in scope when not specifying the types, so it cannot be used. For example, look into this version of your Try Reason example where the types are in a different module, you get the same error you get on your code.

You can qualify the field accessor with the module it is in, like this. Personally I find this super weird as a JS dev.

You can also open the module which I think works better, something like this.

In general it is worth learning better about modules and records as even if they look really similar to JS they are a bit different in a few subtle but important ways :smile: Hope this was helpful


#3

This is a common frustration for beginner. When it comes to record, you have to give the compiler some hints. This problem has been discussed here.


#4

Thanks so much @joakin & @thangngoc89 ! That makes a lot of sense. I guess I was thinking it would somehow… follow the path from one module to the other but I guess not :slight_smile:

I’ll definitely dive into those articles. I need to also read all the reason articles on his blog as well.

I wonder if it would be helpful to have a single module of just types and then just open the file once to import all the apps shared types? Maybe that would be unmaintainable though.

Many thanks!!