Strange behavior in type parameter

type result_1<'a, 'b> =
  | Ok('a)
  | Error('b)

type myPayload = {data: string}

type myPayloadResults<'errorType> = array<result<myPayload, 'errorType>>

let payloadResults: myPayloadResults<string> = [
  Ok({data: "hi"}),
  Ok({data: "bye"}),
  Error("Something wrong happened!"),
]

The compiler doesn’t complain even changing type result to type result_1, as above showed. I don’t quite get if this is a bug or something I don’t fully grasp.

@geohuz Built in result type in rescript, has same signature like the one that you declared. Compiler automatically picks corresponding type, that’s why you don’t see any errors.

3 Likes

Because result and result_1 use constructors with the same names, and because both are in scope, either one is a valid way to parse the contents of payloadResults. By giving playloadResults an explicit type annotation, you’re helping the compiler disambiguate which type you intend to use.

Reusing variant constructor names (and record field names) in the same scope can lead to this kind of ambiguity, which is why doing so is typically discouraged. If you use a unique name for your constructors, e.g. Ok2('a) | Error2('b) then there’s no ambiguity, and no need to annotate the type of payloadResults.

May I ask why you’re defining your own result type?

I’m a newbie learning rescript from the official doc, the code is from “type parameter” and I tried it in playground. So I have no idea there is a result type in the stdlib, so you should ask “why the official doc using code-snippet from stdlib without mention it?”

2 Likes