529 lines
11 KiB
Text
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).
|