Hi all, back to Rescript after a couple of years. Just had a question on how I would do the following in TS in Rescript, specifically the enforcement of the literal types generated per withQuestionMark call and the use of the generic D as an extension of generic V
You can use polymorphic variants for this which are structurally typed and represented as strings at runtime (so type-safe coercion to string works with the :> operator).
let withQuestionMark = (defaultValue: 'value, toString: 'value => string) =>
(~value=?) =>
switch value {
| Some(value) => value->toString + "?"
| None => defaultValue->toString + "?"
}
let questionABC = withQuestionMark(#a, (v: [#a | #b | #c]) => (v :> string))
let questionXYZ = withQuestionMark(#z, (v: [#x | #y | #z]) => (v :> string))
Note that I had to add another parameter toString to the withQuestionMark function.
Thanks for the reply
Is there a way of doing this without the toString so that the defaultValue and the value are always inferred as a particular polymorphic variant?
There is, but we must provide our own generic toString function then and βlieβ to the compiler that this is a string, because it cannot infer it safely at that point:
external toString: 'a => string = "%identity"
let withQuestionMark = (defaultValue: 'value) =>
(~value: option<'value>=?) => // this type annotation is required now!
switch value {
| Some(value) => value->toString + "?"
| None => defaultValue->toString + "?"
}
let questionABC = withQuestionMark((#a: [#a | #b | #c]))
let questionXYZ = withQuestionMark((#z: [#x | #y | #z]))