Skip to content

Structs and Enums

A struct declaration at the top level of a .slint source file defines a named structure type; its fields are written between braces, each a name and a type separated by :, the fields separated by commas, and a struct with no fields is allowed.

Each field’s type can be any property type.

export struct Palette {
fill: color,
gap: length,
}
slint

A ; between fields is a compile error; the compiler tells you to use , instead.

A struct may be prefixed with one or more @rust-attr(...) attributes and may be exported. Declaring a struct whose name matches an already-defined type replaces the earlier type and emits a warning.

A struct value is written as a struct literal that initializes fields by name, { field1: value1, field2: value2 }, with an optional trailing comma.

A field is read with the . operator, as in palette.fill.

export struct Palette {
fill: color,
gap: length,
}
export component Example inherits Window {
out property <Palette> palette: { fill: #f00, gap: 2px };
out property <color> tint: palette.fill;
}
slint

A struct literal need not list every field; an omitted field takes its default value, and members that don’t name a field of the target struct are ignored.

The default value of a struct has every field set to its own default value, unless the field declares its own.

= expression after a field’s type declares a default value for that field:

export struct Player {
name: string = "unknown",
score: int = 100,
}
export component Example {
// player.name is "Foo", player.score is 100
in-out property<Player> player: { name: "Foo" };
}
slint

The expression must be a compile-time constant. It may combine literals, casts, and operators, but referencing a property, an element, or any runtime value is a compile error. A number is only converted to a string when the result is the same in every locale: = 42 is fine, while = 42.1 is a compile error, because the decimal separator depends on the locale.

The default applies whenever an instance of the struct is created without a value for the field: in struct literals that omit the field, in properties of that struct type that are never set, and when the struct is constructed from native code (Rust Player::default(), C++ Player{}, JavaScript new ui.Player(), Python ui.Player()).

Field default values are only supported in named struct declarations. Writing = expression in an anonymous struct type is a compile error.

{ identifier1: type1, identifier2: type2 } is an anonymous struct type. It behaves like a named struct without a name:

export component Example {
in-out property<{name: string, score: int}> player: { name: "Foo", score: 100 };
in-out property<{a: int, }> foo: { a: 3 };
}
slint

Two anonymous struct types with the same fields are the same type. A named struct is only ever equal to itself: it is not interchangeable with an anonymous struct of identical fields.

An enum declaration at the top level defines an enumeration; its values are listed between braces, separated by commas.

An enum shall have at least one value.

A value shall not have the same name as the enum.

The values shall be distinct; - and _ are the same character within a name, so hello-world and hello_world name one value.

No two values shall map to the same generated name, formed by dropping - and _ and capitalizing the first letter of the name and of each word after a separator. hello-world and HelloWorld are different values but map to the same name, so an enum cannot declare both.

export enum Direction { up, down, left, right }
export component Example inherits Window {
in-out property<Direction> heading: Direction.up;
}
slint

An enum value is referenced with the enum name and the value name separated by a dot, as in Direction.up.

The default value of an enum is its first value.

The enum name may be omitted wherever a value of that enum type is the expected type: in a binding, a struct field, an array element, a function or callback argument, and a return value.

export enum CardSuit { clubs, diamonds, hearts, spade }
export struct Card { suit: CardSuit, value: int }
export component Example {
// in a struct field and an array element
out property<Card> card: { suit: hearts, value: 10 };
out property<[CardSuit]> deck: [clubs, diamonds, hearts, spade];
pure function is-red(suit: CardSuit) -> bool {
return suit == hearts || suit == diamonds;
}
// as a function argument
out property<bool> spade-is-red: is-red(spade);
}
slint

In a comparison the name may be omitted only on the right-hand side, which takes the type of the left: card.suit == hearts works, but hearts == card.suit does not, because the left operand has no expected type.


© 2026 SixtyFPS GmbH