Welcome to MkUnion
About
Strongly typed union type in golang that supports generics*
- with exhaustive pattern matching support
- with json marshalling including generics
- and as a bonus, can generate compatible TypeScript types for end-to-end type safety in your application
Why
Historically, in languages like Go that lack native union types, developers have resorted to workarounds such as the Visitor pattern or iota
with switch
statements.
The Visitor pattern requires a lot of boilerplate code and manual crafting of the Accept
method for each type in the union.
Using iota
and switch
statements is not type-safe and can lead to runtime errors, especially when a new type is added and not all case
statements are updated.
On top of that, any data marshalling, like to/from JSON, requires additional, handcrafted code to make it work.
MkUnion solves all of these problems by generating opinionated and strongly typed, meaningful code for you.
Example
//go:tag mkunion:"Shape"
type (
Circle struct {
Radius float64
}
Rectangle struct {
Width float64
Height float64
}
Square struct {
Side float64
}
)
func CalculateArea(s Shape) float64 {
return MatchShapeR1(
s,
func(x *Circle) float64 {
return math.Pi * x.Radius * x.Radius
},
func(x *Rectangle) float64 {
return x.Width * x.Height
},
func(x *Square) float64 {
return x.Side * x.Side
},
)
}
func TestShapeJSON(t *testing.T) {
shape := &Rectangle{
Width: 10,
Height: 20,
}
result, err := shared.JSONMarshal[Shape](shape)
if err != nil {
t.Fatal(err)
}
fmt.Println(string(result))
// Output: {"$type":"example.Rectangle","example.Rectangle":{"Width":10,"Height":20}}
shape2, err := shared.JSONUnmarshal[Shape](result)
if err != nil {
t.Fatal(err)
}
fmt.Printf("%#v", shape2)
// Output: &example.Rectangle{Width:10, Height:20}
}
Watch for changes in the file and generate code on the fly:
Next steps
- Read getting started to learn more.
- Learn more about value proposition