Skip to content

Enums

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.

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:

Terminal window
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/myapp/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.

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

// 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",
};
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,
}

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,
};

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, int640
uint, uint8, uint16, uint32, uint640
float32, float640
boolfalse

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.

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 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/myapp/services/models.ts
export enum Title {
$zero = "",
Mister = "Mr",
Miss = "Miss",
Ms = "Ms",
}

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.

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.

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

Go TypeWorks as Enum
stringYes
int, int8, int16, int32, int64Yes
uint, uint8, uint16, uint32, uint64Yes
float32, float64Yes
byte (uint8)Yes
rune (int32)Yes
boolYes
complex64, complex128No

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

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/myapp/themeservice'
import { BackgroundConfig, BackgroundType } from './bindings/myapp/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/myapp/themeservice'
import { BackgroundConfig, BackgroundType } from './bindings/myapp/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
}

Data Models

Structs, type mapping, and model generation.

Learn More →

Advanced Binding

Directives, code injection, and custom IDs.

Learn More →


Questions? Ask in Discord or check the binding examples.