Hi,
Sorry if the answer is somewhere in the docs but I can’t find it.
I was wondering if there’s a never
/ Void
/ Empty type (i.e without inhabitant) with rescript ?
Best,
Matthieu
Hi @praveen ,
Thanks for your answer but I’m looking for a type that can’t be constructed Bottom type - Wikipedia
I’m surprised not to find it in the rescript type system but I guess I can live without it
An abstract type without any functions that return values of that type is similar to never
:
type never
let aFunctionThatCannotBeCalled = (x: never) => Js.log("Hello")
There’s no common predefined type like this that I know of, though. I think because it’s never needed in practice. Do you have a real world use case where you need it?
yes, I like to do something like that in “business” apps :
in a shared “Error” module (used everywhere in the app) :
type never
type t<'a> = BusinessErr('a) | TechErr
type techOnly = t<never>
let f = (x: techOnly) =>
switch x {
| TechErr => "hello"
}
and the compiler shouldn’t complain about a missing case in the pattern matching (but it does in rescript).
I can find workaround without problem, I’m just surprised not to be able to do that.
If you want to constrain a type to a subset, you can use polymorphic variants in ReScript:
type t<'a> = [#BusinessErr('a) | #TechErr]
let f = (x: [#TechErr]) =>
switch x {
| #TechErr => "hello"
}
Have a look at Polymorphic Variant | ReScript Language Manual.
The polymorphic variant answer is nice, but here is another way, in case you wanted to know how to do it in a way that’s like the uninhabited type (aka empty variant, bottom type, …).
As far as I can tell, you can’t do uninhabited types in ReScript directly (it would be something like type never = |
). But you can get the same result with the GADT.
You just have to change your never
type a bit.
// GADT
type rec type_equal<'a, 'b> = T: type_equal<'a, 'a>
// You can never construct a value of this type!
type never = type_equal<unit, int>
type t<'a> = Business_err('a) | Tech_err
type techOnly = t<never>
let f = (x: techOnly) =>
switch x {
// Compiler knows this is the only case you can have.
| Tech_err => "hello"
}
let x = f(Tech_err)
Js.log(x) // prints "hello"
// Won't work!
// let y = f(Business_err("whatever"))
I don’t know if doing this is worth it to you, but you could do it!
Great ! In my opinion, it’s totally worth it !
Thanks a lot ! (and I didn’t know that GADTs were supported by rescript, cool)