@unboxed
type firestoreErrorCode =
| @as("cancelled") Cancelled
| @as("unknown") Unknown
| @as("invalid-argument") InvalidArgument
| @as("deadline-exceeded") DeadlineExceeded
| @as("not-found") NotFound
| @as("already-exists") AlreadyExists
| @as("permission-denied") PermissionDenied
| @as("resource-exhausted") ResourceExhausted
| @as("failed-precondition") FailedPrecondition
| @as("aborted") Aborted
| @as("out-of-range") OutOfRange
| @as("unimplemented") Unimplemented
| @as("internal") Internal
| @as("unavailable") Unavailable
| @as("data-loss") DataLoss
| @as("unauthenticated") Unauthenticated
let code = Cancelled
// Does not work
let e = React.string(code)
But now I want to cast this back to a raw string to pass to React.string, is there a dedicate helper for this or do I need to create a function myself?
:> is the coercion operator. It can coerce any variant that’s only represented by strings into a string (or to float, int etc, if that’s what the variant is represented as at runtime).
Unrelated to your actual question, but you can leverage this fact the other way as well if you add a default case to your variant:
@unboxed
type firestoreErrorCode =
| @as("cancelled") Cancelled
| @as("unknown") Unknown
| @as("invalid-argument") InvalidArgument
| @as("deadline-exceeded") DeadlineExceeded
| @as("not-found") NotFound
| @as("already-exists") AlreadyExists
| @as("permission-denied") PermissionDenied
| @as("resource-exhausted") ResourceExhausted
| @as("failed-precondition") FailedPrecondition
| @as("aborted") Aborted
| @as("out-of-range") OutOfRange
| @as("unimplemented") Unimplemented
| @as("internal") Internal
| @as("unavailable") Unavailable
| @as("data-loss") DataLoss
| @as("unauthenticated") Unauthenticated
// Added this @as(string) case, which will catch anything not specifically matched above
| @as(string) OtherCode
let code = ("cancelled" :> firestoreErrorCode) // Cancelled
let code = ("some random string" :> firestoreErrorCode) // OtherCode("some random string")
there are some ways to model inheritance with rescript type systems, sometimes it’s worth it, sometimes it’s just too cumbersome, so you can try and judge by yourself!
type vehicule<'kind>
type car<'model> = vehicule<[#car]>
type ferrari = car<[#ferrari]>
type bike = vehicule<[#bike]>
@get external getName: vehicule<'kind> => string = "name"
@send external openTrunk: car<'model> => unit = "openTrunk"
@send external goVeryFast: ferrari => unit = "goVeryFast"
@val external myBike: bike = "myBike"
@val external myFerrari: ferrari = "myFerrari"
myBike->getName->Console.log // this works
myFerrari->getName->Console.log // this works too
myBike->openTrunk
/* ^
Error:
This has type: bike (defined as vehicule<[#bike]>)
But this function argument is expecting:
car<'a> (defined as vehicule<[#car]>)
These two variant types have no intersection
*/
This looks interesting, in my code I do have two generic parameters:
/// https://firebase.google.com/docs/reference/js/firestore_.querydocumentsnapshot.md#querydocumentsnapshot_class
type query<'documentdata, 'metadata>
// does not work: The type constructor query expects 2 argument(s),
// but is here applied to 1 argument(s)
type collectionReference<'documentdata, 'metadata> = query<[#collectionReference]>