A data type for untagged unions.
Consider a the following type:
import Untagged.Union
type ISB = Int |+| String |+| Boolean
The type ISB
describes values which can either be an Int
, a String
or a Boolean
. Moreover, it is guaranteed that at runtime, values of type ISB
is directly stored as an Int
, a String
or a Boolean
without any wrappers. This makes it especially useful for FFI.
Note that |+|
is an alias for OneOf
.
In order to create a value of OneOf
, use asOneOf
.
isb1 :: ISB
isb1 = asOneOf 20
isb2 :: ISB
isb2 = asOneOf "foo"
--isb3 :: ISB
--isb3 = asOneOf 3.5
-- isb3 will fail since 3.5 is a Number which is neither
-- an Int, String nor Boolean
The library also defines Undefined
. Combined with OneOf
, it can represent an optional type:
import Literals.Undefined
type OptionalInt = Int |+| Undefined
An alias UndefinedOr
is also provided.
type OptionalInt' = UndefinedOr Int -- Same as `Int |+| Undefined`
To get a purescript value back, use fromOneOf
:
import Data.Maybe
valInt :: Maybe Int
valInt = fromOneOf isb1 -- evaluates to `Just 20`
valString :: Maybe String
valString = fromOneOf isb1 -- evalutes to `Nothing` since isb1 contains an Int
Using OneOf
, describing JS types as records becomes intuitive:
type Props =
{ text :: String -- a required field
-- Optional Fields
, width :: UndefinedOr Number
, height :: UndefinedOr Number
-- Optional and Varying types
, fontSize :: String |+| Number |+| Undefined
}
A coerce
helper is made available to convert records with the same runtime value:
import Untagged.Coercible (coerce)
sampleProps :: Props
sampleProps =
coerce { text: "foo" -- text is required and should be a string
, width: 30.0 -- width is optional, and may be defined, but should be a Number
-- height is optional and may be omitted
, fontSize: "100%" -- fontSize may be defined, and should either be a string or number
}