1 Kumori DSL Type System

The Kumori DSL features a statically-typed system that ensures correctness, consistency, and clarity in your application specifications. By catching errors before deployment, the type system helps you write robust and maintainable code.

1.1 Benefits of a Static Type System

  • Early Error Detection: Catches mistakes (typos, incorrect types) during development, preventing deployment failures.
  • Consistency: Enforces adherence to defined contracts and schemas.
  • Clear Contracts: Reinforces clear interactions between application parts.
  • Improved Readability: Makes code easier to understand and maintain.

1.2 Primitive Types

Kumori DSL provides several built-in primitive types:

  • bool: Boolean values (true or false).
  • string: Unicode text values (e.g., "some-value").
  • number: Numeric values, including integers and floats (e.g., 1, 0.4545).
  • list: A collection of strings or numbers (e.g., ["item1", "item2"] or [1, 2, 3]).
  • any: A universal type that can hold any value. Use it sparingly to bypass type system limitations when necessary.

1.3 Complex Types

1.3.1 Structs

A struct defines a data structure with named fields. Fields can be required or optional (using ?).

alias component struct {
    srv?         Links
    config?      struct open[]
    resource?    struct open[Resource]
    code?        struct open[Code]
    size         struct {
        bandwidth       BandwidthSized
        minbandwidth    BandwidthSized
        mincpu          CPUSized
    }
}

1.3.2 Open Structs

Open structs allow arbitrary additional fields, making them flexible for configurations or resources. They are similar to Go’s map[string]Type or TypeScript’s Map<string, Type>.

  • struct open[]: Accepts any fields with any value type.
  • struct open[Type]: Accepts any fields, but all values must conform to Type.
config struct open[]
resource struct open[Resource]

1.3.3 Unions

Union types (also known as enums) are defined using the | operator. A value of a union type can be any of the specified types.

alias Resource Volume | CA | Certificate | Secret | Domain | Port

1.3.4 Lists

Lists are defined using []Type:

alias StringList []string

1.4 Type Definitions

Kumori DSL provides two ways to define new types: alias and type.

1.4.1 alias

  • Creates a type synonym for an existing type or type expression.
  • Does not introduce a new, distinct type; it simply gives a new name to an existing type.
  • Aliases are interchangeable with the type they refer to.
  • Useful for creating readable names for complex types or defining unions.
alias Port string
alias Volume Registered | InlineVolume

1.4.2 type

  • Creates a new, named type definition.
  • Introduces a distinct type in the type system, even if its structure matches another type.
  • Named types are not interchangeable, even if their structure is identical.
  • Important for strict type identity, modularity, and API contracts.
type MyStruct struct {
    foo string
    bar number
}

When declaring a variable of a named type, you must explicitly instance it through the constructor:

value: MyStruct = MyStruct({ foo "123", bar 456 })

1.4.3 Declaring Custom Types

Custom types can only be declared inside a library block in a .kumori file.

// types.kumori
library {
    type MyConfig struct {
        foo string
        bar? number
    }
}

// my-component.kumori
component MyComponent {
    config MyConfig
    // ... other blocks ...
}

1.5 Optional Fields and Default Values

1.5.1 Optionals

Any field in a struct can be made optional by adding a ? to its name.

alias Example struct {
    requiredField string
    optionalField? number
}

1.5.2 Default Values

Struct fields can have default values. If a field with a default value is omitted, the default is automatically used.

config {
    LogVerbosity: string = "info"
    MaxConnections: number = 100
}
Important

Struct entries within the resource field of artifacts cannot have a default value.

1.6 Assignability

Assignability determines whether a value of one type can be assigned to a variable, field, or parameter of another type.

  • Primitive Types: A value of a primitive type can only be assigned to a variable of the same type.
  • any Type: The any type can accept any value.
  • Aliases: Aliases are fully interchangeable with the types they refer to.
  • Named Types: Named types are not assignable to other types, even if their structure matches.
  • Structs: For a struct to be assignable, all required fields must be present and have assignable types. Optional fields may be omitted. Extra fields are only allowed in open structs.
  • Unions: A value is assignable to a union type if it is assignable to at least one of the union’s member types.
  • Lists: A list is assignable if all its elements are assignable to the list’s element type.

1.7 Built-in Functions

The Kumori DSL type system exposes functions as first-class types. However, you can only use the built-in functions provided by the compiler. You cannot define your own functions.

func Format(i number, base number) string

For further reading, see the kumori/builtin package documentation.