gui/docs/ref/wails-v3/features/bindings/enums.mdx
Snider 4bdbb68f46
Some checks failed
Security Scan / security (push) Failing after 9s
Test / test (push) Failing after 1m21s
refactor: update import path from go-config to core/config
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-14 10:26:36 +00:00

529 lines
11 KiB
Text

---
title: Enums
description: Automatic enum generation from Go constants
sidebar:
order: 4
---
import { Card, CardGrid } from "@astrojs/starlight/components";
## 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.
:::note
Unlike Wails v2, there is **no need to call `EnumBind`** or register enums manually. The generator discovers them automatically from your source code.
:::
## Quick Start
**Define a named type with constants in Go:**
```go
type Status string
const (
StatusActive Status = "active"
StatusPending Status = "pending"
StatusClosed Status = "closed"
)
```
**Use the type in a struct or service method:**
```go
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:**
```javascript
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.
## Defining Enums
An enum in Wails is a **named type** with an underlying basic type, combined with **const declarations** of that type.
### String Enums
```go
// 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:**
```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:**
```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
```go
type Priority int
const (
PriorityLow Priority = 0
PriorityMedium Priority = 1
PriorityHigh Priority = 2
)
```
**Generated TypeScript:**
```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`:
```go
// 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:**
```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:**
```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,
};
```
:::tip
**Named types** (`type Title string`) generate native TypeScript `enum` declarations with a `$zero` member.
**Type aliases** (`type Age = int`) generate a `type` + `const` namespace pair without `$zero`.
:::
## 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`:
```typescript
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:
```go
type Person struct {
Title Title
Name string
Age Age
}
```
**Generated TypeScript:**
```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:
```go
// services/types.go
package services
type Title string
const (
Mister Title = "Mr"
Miss Title = "Miss"
Ms Title = "Ms"
)
```
```go
// 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:
```typescript
// bindings/myapp/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:
```go
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 types** — `complex64` and `complex128` cannot be enum underlying types
## Complete Example
**Go:**
```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):**
```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):**
```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
}
```
## Next Steps
<CardGrid>
<Card title="Data Models" icon="document">
Structs, type mapping, and model generation.
[Learn More →](/features/bindings/models)
</Card>
<Card title="Method Binding" icon="rocket">
Bind Go methods to the frontend.
[Learn More →](/features/bindings/methods)
</Card>
<Card title="Advanced Binding" icon="setting">
Directives, code injection, and custom IDs.
[Learn More →](/features/bindings/advanced)
</Card>
<Card title="Best Practices" icon="approve-check">
Binding design patterns.
[Learn More →](/features/bindings/best-practices)
</Card>
</CardGrid>
---
**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [binding examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/binding).