docs: document automatic enum generation in binding generator (#4973)

* docs: document automatic enum generation in binding generator (#4972)

Add dedicated Enums page covering string/integer/type-alias enums,
$zero values, struct field typing, imported package enums, supported
types, and limitations. Fix inaccurate enum section in Data Models
page and add both Data Models and Enums to sidebar navigation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add enum generation changelog entry (#4972)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: address review feedback on enum documentation

- Add bool → false to $zero value table
- Fix title.String() → string(title) in imported package example
- Clarify $zero defaults apply to class output, not interfaces
- Improve iota limitation wording for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lea Anthony 2026-02-08 21:45:23 +11:00 committed by GitHub
commit bbc4e532c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 545 additions and 18 deletions

View file

@ -138,6 +138,8 @@ export default defineConfig({
items: [
{ label: "Method Binding", link: "/features/bindings/methods" },
{ label: "Services", link: "/features/bindings/services" },
{ label: "Data Models", link: "/features/bindings/models" },
{ label: "Enums", link: "/features/bindings/enums" },
{ label: "Advanced Binding", link: "/features/bindings/advanced" },
{ label: "Best Practices", link: "/features/bindings/best-practices" },
],

View file

@ -0,0 +1,529 @@
---
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).

View file

@ -480,6 +480,8 @@ if (user.nickname) {
### Enums
The binding generator automatically detects Go named types with constants and generates TypeScript enums or JavaScript const objects — including a `$zero` member for Go's zero value and full JSDoc preservation.
```go
type UserRole string
@ -488,26 +490,16 @@ const (
RoleUser UserRole = "user"
RoleGuest UserRole = "guest"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Role UserRole `json:"role"`
}
```
**Generated:**
**Generated TypeScript:**
```javascript
export const UserRole = {
Admin: "admin",
User: "user",
Guest: "guest"
}
export class User {
/** @type {string} */
role = UserRole.User
```typescript
export enum UserRole {
$zero = "",
RoleAdmin = "admin",
RoleUser = "user",
RoleGuest = "guest",
}
```
@ -518,10 +510,12 @@ import { User, UserRole } from './bindings/myapp/models'
const admin = new User({
name: "Admin",
role: UserRole.Admin
role: UserRole.RoleAdmin
})
```
For comprehensive coverage of string enums, integer enums, type aliases, imported package enums, and limitations, see the dedicated **[Enums](/features/bindings/enums)** page.
### Validation
```javascript

View file

@ -17,6 +17,8 @@ After processing, the content will be moved to the main changelog and this file
## Added
<!-- New features, capabilities, or enhancements -->
- Add `-tags` flag to `wails3 build` command for passing custom Go build tags (e.g., `wails3 build -tags gtk4`) (#4957)
- Add documentation for automatic enum generation in binding generator, including dedicated Enums page and sidebar navigation (#4972)
## Changed
<!-- Changes in existing functionality -->