Enums

Enum Bindings

The Wails v3 binding generator automatically detects Go constant types and generates TypeScript enums or JavaScript const objects. No registration, no configuration — just define your types and constants in Go, and the generator handles the rest.

Quick Start

Define a named type with constants in Go:

type Status string

const (
    StatusActive  Status = "active"
    StatusPending Status = "pending"
    StatusClosed  Status = "closed"
)

Use the type in a struct or service method:

type Ticket struct {
    ID     int    `json:"id"`
    Title  string `json:"title"`
    Status Status `json:"status"`
}

Generate bindings:

bash
wails3 generate bindings

The generator output will report enum counts alongside models:

3 Enums, 5 Models

Use in your frontend:

import { Ticket, Status } from './bindings/changeme/models'

const ticket = new Ticket({
    id: 1,
    title: "Bug report",
    status: Status.StatusActive
})

That’s it! The enum type is enforced in both Go and JavaScript/TypeScript.

Defining Enums

An enum in Wails is a named type with an underlying basic type, combined with const declarations of that type.

String Enums

// Title is a title
type Title string

const (
    // Mister is a title
    Mister Title = "Mr"
    Miss   Title = "Miss"
    Ms     Title = "Ms"
    Mrs    Title = "Mrs"
    Dr     Title = "Dr"
)

Generated TypeScript:

/**
 * Title is a title
 */
export enum Title {
    /**
     * The Go zero value for the underlying type of the enum.
     */
    $zero = "",

    /**
     * Mister is a title
     */
    Mister = "Mr",
    Miss = "Miss",
    Ms = "Ms",
    Mrs = "Mrs",
    Dr = "Dr",
}

Generated JavaScript:

/**
 * Title is a title
 * @readonly
 * @enum {string}
 */
export const Title = {
    /**
     * The Go zero value for the underlying type of the enum.
     */
    $zero: "",

    /**
     * Mister is a title
     */
    Mister: "Mr",
    Miss: "Miss",
    Ms: "Ms",
    Mrs: "Mrs",
    Dr: "Dr",
};

Integer Enums

type Priority int

const (
    PriorityLow    Priority = 0
    PriorityMedium Priority = 1
    PriorityHigh   Priority = 2
)

Generated TypeScript:

export enum Priority {
    /**
     * The Go zero value for the underlying type of the enum.
     */
    $zero = 0,

    PriorityLow = 0,
    PriorityMedium = 1,
    PriorityHigh = 2,
}

Type Alias Enums

Go type aliases (=) also work, but generate a slightly different output — a type definition plus a const object, rather than a native TypeScript enum:

// Age is an integer with some predefined values
type Age = int

const (
    NewBorn    Age = 0
    Teenager   Age = 12
    YoungAdult Age = 18

    // Oh no, some grey hair!
    MiddleAged Age = 50
    Mathusalem Age = 1000 // Unbelievable!
)

Generated TypeScript:

/**
 * Age is an integer with some predefined values
 */
export type Age = number;

/**
 * Predefined constants for type Age.
 * @namespace
 */
export const Age = {
    NewBorn: 0,
    Teenager: 12,
    YoungAdult: 18,

    /**
     * Oh no, some grey hair!
     */
    MiddleAged: 50,

    /**
     * Unbelievable!
     */
    Mathusalem: 1000,
};

Generated JavaScript:

/**
 * Age is an integer with some predefined values
 * @typedef {number} Age
 */

/**
 * Predefined constants for type Age.
 * @namespace
 */
export const Age = {
    NewBorn: 0,
    Teenager: 12,
    YoungAdult: 18,

    /**
     * Oh no, some grey hair!
     */
    MiddleAged: 50,

    /**
     * Unbelievable!
     */
    Mathusalem: 1000,
};

The $zero Value

Every named-type enum includes a special $zero member representing the Go zero value for the underlying type:

Underlying Type $zero Value
string ""
int, int8, int16, int32, int64 0
uint, uint8, uint16, uint32, uint64 0
float32, float64 0
bool false

When a struct field uses an enum type and no value is provided, the constructor defaults to $zero:

export class Person {
    "Title": Title;

    constructor($$source: Partial<Person> = {}) {
        if (!("Title" in $$source)) {
            this["Title"] = Title.$zero;  // defaults to ""
        }
        Object.assign(this, $$source);
    }
}

This ensures type-safe initialisation when generating classes — enum fields are never undefined. When generating TypeScript interfaces (using -i), there is no constructor and fields may be absent as usual.

Using Enums in Structs

When a struct field has an enum type, the generated code preserves that type rather than falling back to the primitive:

type Person struct {
    Title Title
    Name  string
    Age   Age
}

Generated TypeScript:

export class Person {
    "Title": Title;
    "Name": string;
    "Age": Age;

    constructor($$source: Partial<Person> = {}) {
        if (!("Title" in $$source)) {
            this["Title"] = Title.$zero;
        }
        if (!("Name" in $$source)) {
            this["Name"] = "";
        }
        if (!("Age" in $$source)) {
            this["Age"] = 0;
        }

        Object.assign(this, $$source);
    }
}

The Title field is typed as Title, not string. This gives your IDE full autocompletion and type checking on enum values.

Enums from Imported Packages

Enums defined in separate packages are fully supported. They are generated into the corresponding package directory:

// services/types.go
package services

type Title string

const (
    Mister Title = "Mr"
    Miss   Title = "Miss"
    Ms     Title = "Ms"
)
// main.go
package main

import "myapp/services"

func (*GreetService) Greet(name string, title services.Title) string {
    return "Hello " + string(title) + " " + name
}

The Title enum is generated in the services models file, and import paths are resolved automatically:

// bindings/changeme/services/models.ts
export enum Title {
    $zero = "",
    Mister = "Mr",
    Miss = "Miss",
    Ms = "Ms",
}

Enum Methods

You can add methods to your enum types in Go. These don’t affect binding generation but provide useful server-side functionality:

type Title string

func (t Title) String() string {
    return string(t)
}

const (
    Mister Title = "Mr"
    Miss   Title = "Miss"
)

The generated enum is identical whether or not Go methods exist on the type.

Comments and Documentation

The generator preserves Go comments as JSDoc in the generated output:

  • Type comments become the enum’s doc comment
  • Const group comments become section separators
  • Individual const comments become member doc comments
  • Inline comments are preserved where possible

This means your IDE will show documentation for enum values on hover.

Supported Underlying Types

The binding generator supports enums with the following Go underlying types:

Go Type Works as Enum
string Yes
int, int8, int16, int32, int64 Yes
uint, uint8, uint16, uint32, uint64 Yes
float32, float64 Yes
byte (uint8) Yes
rune (int32) Yes
bool Yes
complex64, complex128 No

Limitations

The following are not supported for enum generation:

  • Generic types — Type parameters prevent constant detection
  • Types with custom json.Marshaler or encoding.TextMarshaler — Custom serialisation means the generated values may not match runtime behaviour, so the generator skips these
  • Constants whose values cannot be statically evaluated or represented — Constants must have known, representable values in their underlying type. Standard iota patterns work fine since the compiler resolves them to concrete values
  • Complex number typescomplex64 and complex128 cannot be enum underlying types

Complete Example

Go:

package main

import (
    "github.com/wailsapp/wails/v3/pkg/application"
)

// BackgroundType defines the type of background
type BackgroundType string

const (
    BackgroundSolid    BackgroundType = "solid"
    BackgroundGradient BackgroundType = "gradient"
    BackgroundImage    BackgroundType = "image"
)

type BackgroundConfig struct {
    Type  BackgroundType `json:"type"`
    Value string         `json:"value"`
}

type ThemeService struct{}

func (*ThemeService) GetBackground() BackgroundConfig {
    return BackgroundConfig{
        Type:  BackgroundSolid,
        Value: "#ffffff",
    }
}

func (*ThemeService) SetBackground(config BackgroundConfig) error {
    // Apply background
    return nil
}

func main() {
    app := application.New(application.Options{
        Services: []application.Service{
            application.NewService(&ThemeService{}),
        },
    })
    app.Window.New()
    app.Run()
}

Frontend (TypeScript):

import { GetBackground, SetBackground } from './bindings/changeme/themeservice'
import { BackgroundConfig, BackgroundType } from './bindings/changeme/models'

// Get current background
const bg = await GetBackground()

// Check the type using enum values
if (bg.type === BackgroundType.BackgroundSolid) {
    console.log("Solid background:", bg.value)
}

// Set a new background
await SetBackground(new BackgroundConfig({
    type: BackgroundType.BackgroundGradient,
    value: "linear-gradient(to right, #000, #fff)"
}))

Frontend (JavaScript):

import { GetBackground, SetBackground } from './bindings/changeme/themeservice'
import { BackgroundConfig, BackgroundType } from './bindings/changeme/models'

// Use enum values for type-safe comparisons
const bg = await GetBackground()

switch (bg.type) {
    case BackgroundType.BackgroundSolid:
        applySolid(bg.value)
        break
    case BackgroundType.BackgroundGradient:
        applyGradient(bg.value)
        break
    case BackgroundType.BackgroundImage:
        applyImage(bg.value)
        break
}

Next Steps

Data Models

Structs, type mapping, and model generation.

Learn More →

Method Binding

Bind Go methods to the frontend.

Learn More →

Advanced Binding

Directives, code injection, and custom IDs.

Learn More →

Best Practices

Binding design patterns.

Learn More →


Questions? Ask in Discord or check the binding examples.

Edit page

Last updated: