{"id":25220102,"url":"https://github.com/widmogrod/mkunion","last_synced_at":"2025-10-25T18:31:26.798Z","repository":{"id":60188442,"uuid":"541522947","full_name":"widmogrod/mkunion","owner":"widmogrod","description":"Strongly typed union type in golang.","archived":false,"fork":false,"pushed_at":"2024-07-14T20:55:32.000Z","size":5133,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-07-15T13:10:26.415Z","etag":null,"topics":["generator","go","golang","golang-library","golang-tools","reducer","traversal","union-types","visitor-pattern"],"latest_commit_sha":null,"homepage":"https://widmogrod.github.io/mkunion/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/widmogrod.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-26T10:13:54.000Z","updated_at":"2024-07-15T13:10:26.415Z","dependencies_parsed_at":"2023-02-12T16:31:41.983Z","dependency_job_id":"df1b787b-3516-4f7f-b987-d7cdf61c7b01","html_url":"https://github.com/widmogrod/mkunion","commit_stats":{"total_commits":771,"total_committers":2,"mean_commits":385.5,"dds":"0.024643320363164745","last_synced_commit":"ca5eaabb8140dbadb26c62f1210ab197f6564f98"},"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widmogrod%2Fmkunion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widmogrod%2Fmkunion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widmogrod%2Fmkunion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widmogrod%2Fmkunion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/widmogrod","download_url":"https://codeload.github.com/widmogrod/mkunion/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238195466,"owners_count":19432105,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generator","go","golang","golang-library","golang-tools","reducer","traversal","union-types","visitor-pattern"],"created_at":"2025-02-10T21:50:11.741Z","updated_at":"2025-10-25T18:31:26.792Z","avatar_url":"https://github.com/widmogrod.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Welcome to MkUnion\n[![Go Reference](https://pkg.go.dev/badge/github.com/widmogrod/mkunion.svg)](https://pkg.go.dev/github.com/widmogrod/mkunion)\n[![Go Report Card](https://goreportcard.com/badge/github.com/widmogrod/mkunion)](https://goreportcard.com/report/github.com/widmogrod/mkunion)\n[![codecov](https://codecov.io/gh/widmogrod/mkunion/branch/main/graph/badge.svg?token=3Z3Z3Z3Z3Z)](https://codecov.io/gh/widmogrod/mkunion)\n\n```bash\ngo install github.com/widmogrod/mkunion/cmd/mkunion@v1.26.1\n```\n\n```\nmkunion watch -g ./...\n```\n\n## About\nStrongly typed **union type** in golang that supports generics*.\n\n* with exhaustive _pattern matching_ support\n* with _json marshalling_ including generics\n* and as a bonus, can generate compatible TypeScript types for end-to-end type safety in your application\n\n## Why\nHistorically, in languages like Go that lack native union types, developers have resorted to workarounds such as the Visitor pattern or `iota` with `switch` statements.\n\nThe Visitor pattern requires a lot of boilerplate code and manual crafting of the `Accept` method for each type in the union.\nUsing `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.\n\nOn top of that, any data marshalling, like to/from JSON, requires additional, handcrafted code to make it work.\n\nMkUnion solves all of these problems by generating opinionated and strongly typed, meaningful code for you.\n\n## Examples\n\n### Example 1: Union definition and pattern matching with JSON marshaling\n\n```go\n//go:tag mkunion:\"Shape\"\ntype (\n    Circle struct{ Radius float64 }\n    Rectangle struct{ Width, Height float64 }\n    Triangle struct{ Base, Height float64 }\n)\n\n// Generated code provides:\narea := MatchShapeR1(\n    shape,\n    func(c *Circle) float64 { return math.Pi * c.Radius * c.Radius },\n    func(r *Rectangle) float64 { return r.Width * r.Height },\n    func(t *Triangle) float64 { return 0.5 * t.Base * t.Height },\n)\n```\n\n### Example 2: Result Type for Error Handling\n\n```go\n//go:tag mkunion:\"Option[T]\"\ntype (\n\tNone[T any] struct{}\n\tSome[T any] struct{ Value T }\n)\n\n//go:tag mkunion:\"Result[T, E]\"\ntype (\n\tOk[T, E any]  struct{ Value T }\n\tErr[T, E any] struct{ Error E }\n)\n\ntype User struct{ Name string }\n\ntype APIError struct {\n\tCode    int\n\tMessage string\n}\n\n// FetchResult combine unions for rich error handling\ntype FetchResult = Result[Option[User], APIError]\n\n// handleFetch uses nested pattern matching to handle result\nfunc handleFetch(result FetchResult) string {\n\treturn MatchResultR1(result,\n\t\tfunc(ok *Ok[Option[User], APIError]) string {\n\t\t\treturn MatchOptionR1(ok.Value,\n\t\t\t\tfunc(*None[User]) string { return \"User not found\" },\n\t\t\t\tfunc(some *Some[User]) string {\n\t\t\t\t\treturn fmt.Sprintf(\"Found user: %s\", some.Value.Name)\n\t\t\t\t},\n\t\t\t)\n\t\t},\n\t\tfunc(err *Err[Option[User], APIError]) string {\n\t\t\treturn fmt.Sprintf(\"API error: %v\", err.Error)\n\t\t},\n\t)\n}\n\n```\n\n**Important:** Generic unions MUST specify their type parameters in the tag. The type parameter names in the tag must match those used in the variant types.\n\n### Example 3: AST and Recursive Types\n\n```go title=\"example/calculator_example.go\"\n//go:tag mkunion:\"Calc\"\ntype (\n    Lit struct{ V int }\n    Sum struct{ Left, Right Calc }\n    Mul struct{ Left, Right Calc }\n)\n```\n\n### Example 4: States for State Machines or Events for Event Sourcing\n\n```go\n//go:tag mkunion:\"OrderState\"\ntype (\n    Draft struct{ Items []Item }\n    Submitted struct{ OrderID string; Items []Item }\n    Shipped struct{ OrderID string; TrackingNumber string }\n    Delivered struct{ OrderID string; DeliveredAt time.Time }\n)\n```\n\n### Example 5: HTTP API responses\n\n```go\n//go:tag mkunion:\"APIResponse[T]\"\ntype (\n    Success[T any] struct{ Data T; Status int }\n    ValidationError[T any] struct{ Errors []string }\n    ServerError[T any] struct{ Message string; Code string }\n)\n```\n\n### Example 6: Configuration type\n```go\n//go:tag mkunion:\"Config\"  \ntype (\n    FileConfig struct{ Path string }\n    EnvConfig struct{ Prefix string }\n    DefaultConfig struct{}\n)\n```\n\n\n## Next\n\n- Read [getting started](https://widmogrod.github.io/mkunion/getting_started/) to learn more.\n- Learn more about [value proposition](https://widmogrod.github.io/mkunion/value_proposition/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwidmogrod%2Fmkunion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwidmogrod%2Fmkunion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwidmogrod%2Fmkunion/lists"}