列挙型
Go 定数からの列挙型の自動生成
列挙型のバインディング
Wails v3 のバインディングジェネレーターは、Go の定数型を自動的に検出し、TypeScript の列挙型または JavaScript の const オブジェクトを生成します。登録も設定も不要です。Go で型と定数を定義するだけで、残りはジェネレーターが処理します。
クイックスタート
Go で、定数を持つ名前付き型を定義します。
type Status string
const (
StatusActive Status = "active"
StatusPending Status = "pending"
StatusClosed Status = "closed"
)構造体またはサービスメソッドでその型を使用します。
type Ticket struct {
ID int `json:"id"`
Title string `json:"title"`
Status Status `json:"status"`
}バインディングを生成します。
wails3 generate bindings
ジェネレーターの出力には、モデル数とともに列挙型の数が表示されます。
3 Enums, 5 Modelsフロントエンドで使用します。
import { Ticket, Status } from './bindings/changeme/models'
const ticket = new Ticket({
id: 1,
title: "Bug report",
status: Status.StatusActive
})以上です。列挙型は Go と JavaScript/TypeScript の両方で適用されます。
列挙型の定義
Wails の列挙型は、基底となる基本型を持つ名前付き型と、その型のconst 宣言を組み合わせたものです。
文字列列挙型
// 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"
)生成される 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",
}生成される 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
)生成される TypeScript:
export enum Priority {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = 0,
PriorityLow = 0,
PriorityMedium = 1,
PriorityHigh = 2,
}型エイリアスの列挙型
Go の型エイリアス(=)も使用できますが、生成される出力は少し異なります。TypeScript ネイティブのenumではなく、型定義と const オブジェクトが生成されます。
// 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!
)生成される 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,
};生成される 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,
};$zero値
名前付き型の各列挙型には、基底型のGo ゼロ値を表す特別な$zeroメンバーが含まれます。
| 基底型 | $zero値 |
|---|---|
string |
"" |
int、int8、int16、int32、int64 |
0 |
uint、uint8、uint16、uint32、uint64 |
0 |
float32、float64 |
0 |
bool |
false |
構造体のフィールドで列挙型を使用し、値が指定されていない場合、コンストラクターはデフォルトで$zeroを使用します。
export class Person {
"Title": Title;
constructor($$source: Partial<Person> = {}) {
if (!("Title" in $$source)) {
this["Title"] = Title.$zero; // defaults to ""
}
Object.assign(this, $$source);
}
}これにより、クラスを生成するときに型安全な初期化が保証され、列挙型フィールドがundefinedになることはありません。TypeScript インターフェースを生成する場合(-iを使用)はコンストラクターがないため、通常どおりフィールドが存在しないことがあります。
構造体での列挙型の使用
構造体のフィールドが列挙型である場合、生成されるコードはプリミティブ型にフォールバックせず、その型を保持します。
type Person struct {
Title Title
Name string
Age Age
}生成される 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);
}
}Titleフィールドの型はstringではなくTitleです。これにより、IDE で列挙値に対する完全な自動補完と型チェックを利用できます。
インポートしたパッケージの列挙型
別のパッケージで定義された列挙型も完全にサポートされています。対応するパッケージディレクトリに生成されます。
// 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
}Title列挙型はservicesモデルファイルに生成され、インポートパスは自動的に解決されます。
// bindings/changeme/services/models.ts
export enum Title {
$zero = "",
Mister = "Mr",
Miss = "Miss",
Ms = "Ms",
}列挙型のメソッド
Go では列挙型にメソッドを追加できます。これらはバインディングの生成には影響しませんが、サーバー側で便利な機能を提供します。
type Title string
func (t Title) String() string {
return string(t)
}
const (
Mister Title = "Mr"
Miss Title = "Miss"
)その型に Go メソッドが存在するかどうかにかかわらず、生成される列挙型は同一です。
コメントとドキュメント
ジェネレーターは、Go のコメントを生成出力内の JSDoc として保持します。
- 型のコメントは、列挙型のドキュメントコメントになります
- const グループのコメントは、セクションの区切りになります
- 個々の const のコメントは、メンバーのドキュメントコメントになります
- インラインコメントは、可能な限り保持されます
これにより、列挙値にカーソルを合わせると、IDE にドキュメントが表示されます。
サポートされる基底型
バインディングジェネレーターは、次の Go 基底型を持つ列挙型をサポートします。
| Go の型 | 列挙型として使用可能 |
|---|---|
string |
はい |
int、int8、int16、int32、int64 |
はい |
uint、uint8、uint16、uint32、uint64 |
はい |
float32、float64 |
はい |
byte(uint8) |
はい |
rune(int32) |
はい |
bool |
はい |
complex64、complex128 |
いいえ |
制限事項
列挙型の生成では、以下はサポートされていません:
- ジェネリック型 — 型パラメーターがあると定数を検出できません
- カスタムの
json.Marshalerまたはencoding.TextMarshalerを持つ型 — カスタムシリアライズを使用すると、生成された値が実行時の動作と一致しない可能性があるため、ジェネレーターはこれらをスキップします - 値を静的に評価または表現できない定数 — 定数には、基底型で表現できる既知の値が必要です。標準的な
iotaパターンはコンパイラーによって具体的な値に解決されるため、問題なく機能します - 複素数型 —
complex64とcomplex128は列挙型の基底型にはできません
完全な例
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()
}フロントエンド(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)"
}))フロントエンド(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
}次のステップ
構造体、型マッピング、モデル生成について説明します。
Go のメソッドをフロントエンドにバインドします。
ディレクティブ、コードインジェクション、カスタム ID について説明します。
バインディングの設計パターンについて説明します。