enumx

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 7 Imported by: 0

README ΒΆ

enumx logo

enumx

Define your enum once. `enumx` generates the type-safe Go API.

enumx is a modern, boilerplate-free enum toolkit for Go. It provides two layers of usage:

  1. Zero-Codegen Runtime Enums: Quick, flexible, generic enums constructed at runtime.
  2. AST-based Code Generation: Type-safe, struct-field based enums without writing type or const manually.

πŸš€ The Killer Feature: enumx-gen

Tired of writing type Status string and defining repetitive constants? Use the AST code generator. The definition file acts as the ultimate Single Source of Truth.

1. Define your enums (Once)

Create an enums.go file with the //go:build ignore directive:

//go:build ignore
//go:generate enumx generate

package main
import "github.com/bakhod1r/enumx"

// Omitting the type name automatically infers it (e.g. StatusType)
var Status = enumx.Define("pending", "active", "blocked")

// Or explicitly specify it: enumx.Define("Role", "admin", "user")
var Roles = enumx.Define("Role", "admin", "user")

2. Generate

Run go generate. enumx will parse the AST and automatically generate enums_enumx_gen.go with all the boilerplate (type StatusType string, constants, etc.).

3. Use with 100% Type-Safety

Your IDE will now auto-complete everything perfectly, with zero hardcoded strings in your business logic!

// Direct typed field access!
Statuses.Active               // "active"
Statuses.Pending              // "pending"

// Clean Validation & Comparison
Statuses.Has(Statuses.Active) // true
if val == Statuses.Active { ... }

// Parsing External Input
val, err := Statuses.Parse("pending")

πŸ—οΈ Simple Runtime Enums (No Codegen)

If you just want a quick enum without code generation, you can use the runtime builder:

// Immutable
status := enumx.New("pending", "active", "blocked")
status.Has("active")        // true
status.Values()             // [pending active blocked]

value, _ := status.Parse("active")
value.Is("active")          // true
value.Valid()               // true
value.String()              // "active"

You can even create mutable generic sets:

codes := enumx.NewMutable[int]()
codes.Add(200).Add(404).Add(500)

⚑ Integration Features

enumx comes with powerful built-in extensions for business logic:

  • Exhaustive Matching: enumx.MatchBuilder[Status, string](val).Case(...).Must()
  • State Machines (FSM): enumx.AddTransition(Statuses.Pending, Statuses.Active)
  • Bitmask Flags: var perms enumx.FlagSet[Permission]
  • i18n & Meta: val.Label("uz")

Installation

go get github.com/bakhod1r/enumx

Documentation ΒΆ

Index ΒΆ

Examples ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var (
	// ErrInvalidEnum indicates that the enum value is not registered or valid.
	ErrInvalidEnum = errors.New("invalid enum value")

	// ErrEmptyEnum indicates that the enum value is empty.
	ErrEmptyEnum = errors.New("empty enum value")
)

Functions ΒΆ

func AddTransition ΒΆ

func AddTransition[T ~string](from, to T)

AddTransition is a simplified helper to register a single state transition.

func CanTransition ΒΆ

func CanTransition[T ~string](current, next T) bool

CanTransition checks if moving from the current state to the next state is a registered valid transition.

func ClearFlag ΒΆ

func ClearFlag[T Integer](mask *T, flag T)

ClearFlag clears a specific flag from a bitmask.

func Contains ΒΆ

func Contains[T ~string](val T, collection ...T) bool

Contains checks if the enum value is within the provided collection. Functionally identical to IsAny, provided for API ergonomics.

func Define ΒΆ

func Define(typeName string, values ...string) any

Define is a marker function used exclusively by the enumx-gen code generator. It should only be used in files with the `//go:build ignore` directive. The first argument is the name of the generated Go type (e.g., "Status"). The remaining arguments are the enum values.

func FormatFlags ΒΆ

func FormatFlags[T Integer](mask T) string

FormatFlags formats a bitmask into a string representation separated by " | ". If a flag is not registered, it is ignored in the output.

func HasFlag ΒΆ

func HasFlag[T Integer](mask, flag T) bool

HasFlag checks if a bitmask contains a specific flag.

func Is ΒΆ

func Is[T ~string](val, target T) bool

Is checks if the enum value is exactly equal to the target.

func IsAny ΒΆ

func IsAny[T ~string](val T, targets ...T) bool

IsAny checks if the enum value matches any of the provided targets.

func IsNot ΒΆ

func IsNot[T ~string](val, target T) bool

IsNot checks if the enum value is not equal to the target.

func IsValid ΒΆ

func IsValid[T ~string](val T) bool

IsValid checks if the provided value is a valid, registered enum value. Returns false if the value is empty, not registered, or if the type itself hasn't been registered.

func LocaleLabel ΒΆ

func LocaleLabel[T ~string](val T, locale string) string

LocaleLabel returns the localized label for an enum value given a locale code. If the locale is not found, it falls back to its raw string representation.

func MarshalJSON ΒΆ

func MarshalJSON[T ~string](v T) ([]byte, error)

MarshalJSON helps marshal an enum type T into a JSON string, ensuring it is valid. By default, Go automatically marshals underlying string types, but using this ensures invalid enum values are caught at marshal time.

Example:

func (s Status) MarshalJSON() ([]byte, error) {
    return enumx.MarshalJSON(s)
}

func Match ΒΆ

func Match[T ~string, R any](val T, cases Cases[T, R]) R

Match performs an exhaustive switch-like check over the enum value. It ensures that all registered values of T are handled in the cases map. If a case is missing for a registered enum, it panics. If the provided value itself is invalid, it also panics. This provides a runtime guarantee of exhaustiveness, catching missing cases during tests.

Example ΒΆ
package main

import (
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

const RoleUser Role = "user"

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	role := RoleUser

	message := enumx.Match(role, enumx.Cases[Role, string]{
		RoleAdmin: func() string { return "Welcome, Admin!" },
		RoleUser:  func() string { return "Welcome, User!" },
		RoleGuest: func() string { return "Welcome, Guest!" },
	})

	fmt.Println(message)
}
Output:
Welcome, User!

func Meta ΒΆ

func Meta[T ~string, M any](val T) (M, bool)

Meta retrieves the custom metadata of type M attached to an enum value of type T. It returns the typed metadata and true if found, otherwise returns the zero value and false.

func Parse ΒΆ

func Parse[T ~string](val string) (T, error)

Parse safely parses a string into the enum type T. It validates the string against the registered values for type T. Returns ErrEmptyEnum if the input string is empty. Returns ErrInvalidEnum (wrapped with context) if the value is not registered.

Example ΒΆ
package main

import (
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	role, err := enumx.Parse[Role]("admin")
	if err != nil {
		panic(err)
	}
	fmt.Println(role)
}
Output:
admin

func ParseFlags ΒΆ

func ParseFlags[T Integer](s string) (T, error)

ParseFlags parses a string separated by " | " into a bitmask of type T.

func Register ΒΆ

func Register[T ~string](values ...T)

Register registers the valid values for enum type T. This should be called in the init() function of the package where the enum is defined.

func RegisterFlags ΒΆ

func RegisterFlags[T Integer](flags map[T]string)

RegisterFlags registers the string representations for bitmask flags of type T.

func RegisterLocales ΒΆ

func RegisterLocales[T ~string](val T, locales map[string]string)

RegisterLocales registers localized labels for a specific enum value. The locales argument is a map where the key is the locale code (e.g., "en", "uz") and the value is the translated label.

Example ΒΆ
package main

import (
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

const RoleAdmin Role = "admin"

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	enumx.RegisterLocales(RoleAdmin, map[string]string{
		"en": "Administrator",
		"uz": "Tizim ma'muri",
	})

	fmt.Println(enumx.LocaleLabel(RoleAdmin, "uz"))
	fmt.Println(enumx.LocaleLabel(RoleAdmin, "en"))
}
Output:
Tizim ma'muri
Administrator

func RegisterMeta ΒΆ

func RegisterMeta[T ~string, M any](val T, meta M)

RegisterMeta attaches custom metadata of any type M to a specific enum value of type T.

func RegisterTransitions ΒΆ

func RegisterTransitions[T ~string](transitions ...Transition[T])

RegisterTransitions registers the allowed state transitions for enum type T. This is used to build a zero-allocation finite state machine (FSM).

func Scan ΒΆ

func Scan[T ~string](src any, v *T) error

Scan helps implement the database/sql.Scanner interface. It parses the database value (typically string or []byte) into the enum type.

Example:

func (s *Status) Scan(src any) error {
    return enumx.Scan(src, s)
}

func SetFlag ΒΆ

func SetFlag[T Integer](mask *T, flag T)

SetFlag sets a specific flag in a bitmask.

func UnmarshalJSON ΒΆ

func UnmarshalJSON[T ~string](b []byte, v *T) error

UnmarshalJSON helps safely unmarshal a JSON string into an enum type T. It should be called from the UnmarshalJSON method of the custom enum type.

Example:

func (s *Status) UnmarshalJSON(b []byte) error {
    return enumx.UnmarshalJSON(b, s)
}
Example ΒΆ
package main

import (
	"encoding/json"
	"fmt"

	"github.com/bakhod1r/enumx"
)

type Role string

const (
	RoleAdmin Role = "admin"
	RoleUser  Role = "user"
	RoleGuest Role = "guest"
)

func init() {
	enumx.Register(RoleAdmin, RoleUser, RoleGuest)
}

func (r Role) Valid() bool                   { return enumx.IsValid(r) }
func (r *Role) UnmarshalJSON(b []byte) error { return enumx.UnmarshalJSON(b, r) }
func (r Role) MarshalJSON() ([]byte, error)  { return enumx.MarshalJSON(r) }

func main() {
	type Request struct {
		UserRole Role `json:"role"`
	}

	validJSON := []byte(`{"role":"admin"}`)
	var req Request
	_ = json.Unmarshal(validJSON, &req)
	fmt.Println("Parsed:", req.UserRole)

	invalidJSON := []byte(`{"role":"hacker"}`)
	var badReq Request
	err := json.Unmarshal(invalidJSON, &badReq)
	fmt.Println("Error:", err != nil)

}
Output:
Parsed: admin
Error: true

func Value ΒΆ

func Value[T ~string](v T) (driver.Value, error)

Value helps implement the database/sql/driver.Valuer interface. It validates the enum and returns its string representation.

Example:

func (s Status) Value() (driver.Value, error) {
    return enumx.Value(s)
}

func Values ΒΆ

func Values[T ~string]() []T

Values returns all registered valid values for enum type T in the order they were registered.

Types ΒΆ

type Cases ΒΆ

type Cases[T ~string, R any] map[T]func() R

Cases represents an exhaustive map of handlers for an enum type.

type Def ΒΆ

type Def[T comparable] struct {
	// contains filtered or unexported fields
}

Def is an immutable enum definition. Create it with New().

func New ΒΆ

func New[T comparable](vals ...T) *Def[T]

New creates an immutable enum definition from the provided values.

func (*Def[T]) Default ΒΆ

func (d *Def[T]) Default(val T)

Default sets the default value for the enum. Panics if val is not a registered member.

func (*Def[T]) Has ΒΆ

func (d *Def[T]) Has(val T) bool

Has returns true if the value is a member of the enum.

func (*Def[T]) IsDefault ΒΆ

func (d *Def[T]) IsDefault(val T) bool

IsDefault reports whether val equals the default value.

func (*Def[T]) Parse ΒΆ

func (d *Def[T]) Parse(val T) (EnumValue[T], error)

Parse validates val and returns a Value wrapping it, or an error.

func (*Def[T]) Values ΒΆ

func (d *Def[T]) Values() []T

Values returns all registered enum values in insertion order.

type Enum ΒΆ

type Enum[T ~string] struct {
	V T
}

Enum is a generic wrapper struct that provides maximum convenience. By embedding this struct in your data models, you get automatic JSON and SQL validation without writing any boilerplate methods (UnmarshalJSON, Scan, etc.).

func NewEnum ΒΆ

func NewEnum[T ~string](val T) (Enum[T], error)

NewEnum creates a new wrapped enum value safely.

func (Enum[T]) Label ΒΆ

func (e Enum[T]) Label(lang string) string

Label retrieves the localized label for the enum value if registered.

func (Enum[T]) MarshalJSON ΒΆ

func (e Enum[T]) MarshalJSON() ([]byte, error)

MarshalJSON returns the JSON string representation of the enum.

func (*Enum[T]) Scan ΒΆ

func (e *Enum[T]) Scan(src any) error

Scan implements the database/sql.Scanner interface.

func (Enum[T]) String ΒΆ

func (e Enum[T]) String() string

String returns the string representation. String returns the string representation.

func (*Enum[T]) UnmarshalJSON ΒΆ

func (e *Enum[T]) UnmarshalJSON(b []byte) error

UnmarshalJSON parses and validates the JSON string into the enum.

func (Enum[T]) Valid ΒΆ

func (e Enum[T]) Valid() bool

Valid checks if the wrapped enum value is valid.

func (Enum[T]) Value ΒΆ

func (e Enum[T]) Value() (driver.Value, error)

Value implements the database/sql/driver.Valuer interface.

type EnumValue ΒΆ

type EnumValue[T comparable] struct {
	// contains filtered or unexported fields
}

EnumValue is the result of a successful Parse call. It carries the validated value and provides a rich API.

func (EnumValue[T]) Is ΒΆ

func (v EnumValue[T]) Is(candidate T) bool

Is reports whether the value equals the given candidate.

func (EnumValue[T]) String ΒΆ

func (v EnumValue[T]) String() string

String returns the string representation of the underlying value.

func (EnumValue[T]) Unwrap ΒΆ

func (v EnumValue[T]) Unwrap() T

Unwrap returns the underlying value.

func (EnumValue[T]) Valid ΒΆ

func (v EnumValue[T]) Valid() bool

Valid reports whether this value was successfully parsed from an enum.

type FlagSet ΒΆ

type FlagSet[T ~uint] struct {
	V T
}

FlagSet is a wrapper for bitmask enums to provide a clean OOP API.

func (*FlagSet[T]) Add ΒΆ

func (f *FlagSet[T]) Add(flag T)

Add sets the specified flag.

func (FlagSet[T]) Has ΒΆ

func (f FlagSet[T]) Has(flag T) bool

Has returns true if the specified flag is set.

func (*FlagSet[T]) Remove ΒΆ

func (f *FlagSet[T]) Remove(flag T)

Remove clears the specified flag.

func (FlagSet[T]) String ΒΆ

func (f FlagSet[T]) String() string

String returns the string representation of the set flags.

type Integer ΒΆ

type Integer interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}

Integer defines a constraint that permits any integer type. This is used for bitmask flags.

type Matcher ΒΆ

type Matcher[T ~string, R any] struct {
	// contains filtered or unexported fields
}

Matcher is a builder for exhaustive matching.

func MatchBuilder ΒΆ

func MatchBuilder[T ~string, R any](val T) *Matcher[T, R]

MatchBuilder creates a new Matcher builder for exhaustive evaluation. You must specify the return type R: enumx.MatchBuilder[Status, string](val)

func (*Matcher[T, R]) Case ΒΆ

func (m *Matcher[T, R]) Case(c T, handler func() R) *Matcher[T, R]

Case adds a handler for a specific enum case.

func (*Matcher[T, R]) Must ΒΆ

func (m *Matcher[T, R]) Must() R

Must evaluates the match and panics if the case is not handled.

type MutableDef ΒΆ

type MutableDef[T comparable] struct {
	// contains filtered or unexported fields
}

MutableDef is a thread-safe, mutable enum definition. Create it with NewMutable().

func NewMutable ΒΆ

func NewMutable[T comparable](vals ...T) *MutableDef[T]

NewMutable creates a thread-safe, mutable enum definition.

func (*MutableDef[T]) Add ΒΆ

func (d *MutableDef[T]) Add(val T) *MutableDef[T]

Add appends val to the enum. Returns self for chaining.

func (*MutableDef[T]) Default ΒΆ

func (d *MutableDef[T]) Default(val T)

Default sets the default value for the enum.

func (*MutableDef[T]) Has ΒΆ

func (d *MutableDef[T]) Has(val T) bool

Has returns true if the value is a member of the mutable enum.

func (*MutableDef[T]) IsDefault ΒΆ

func (d *MutableDef[T]) IsDefault(val T) bool

IsDefault reports whether val equals the default value.

func (*MutableDef[T]) Parse ΒΆ

func (d *MutableDef[T]) Parse(val T) (EnumValue[T], error)

Parse validates val and returns a Value wrapping it, or an error.

func (*MutableDef[T]) Remove ΒΆ

func (d *MutableDef[T]) Remove(val T) *MutableDef[T]

Remove deletes val from the enum. Returns self for chaining.

func (*MutableDef[T]) Values ΒΆ

func (d *MutableDef[T]) Values() []T

Values returns all registered enum values in insertion order.

type Transition ΒΆ

type Transition[T ~string] struct {
	From T
	To   T
}

Transition represents a valid state transition from one enum value to another.

Directories ΒΆ

Path Synopsis
cmd
enumx command
example
basic command
codegen command
Code generated by enumx-gen.
Code generated by enumx-gen.
generate command
Code generated by enumx.
Code generated by enumx.
usage command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL