Types
FTL supports the following types: Int
(64-bit), Float
(64-bit), String
, Bytes
(a byte array), Bool
, Time
, Any
(a dynamic type), Unit
(similar to "void"), arrays, maps, data structures, and constant enumerations. Each FTL type is mapped to a corresponding language-specific type. For example in Go Float
is represented as float64
, Time
is represented by time.Time
, and so on. [^1]
Any Go type supported by FTL and referenced by an FTL declaration will be automatically exposed to an FTL type.
For example, the following verb declaration will result in Request
and Response
being automatically translated to FTL types.
type Request struct {}
type Response struct {}
//ftl:verb
func Hello(ctx context.Context, in Request) (Response, error) {
// ...
}
Type enums (sum types)
Sum types are supported by FTL's type system, but aren't directly supported by Go. However they can be approximated with the use of sealed interfaces. To declare a sum type in FTL use the comment directive //ftl:enum
:
//ftl:enum
type Animal interface { animal() }
type Cat struct {}
func (Cat) animal() {}
type Dog struct {}
func (Dog) animal() {}
Value enums
A value enum is an enumerated set of string or integer values.
//ftl:enum
type Colour string
const (
Red Colour = "red"
Green Colour = "green"
Blue Colour = "blue"
)
Type aliases
A type alias is an alternate name for an existing type. It can be declared like so:
//ftl:typealias
type Alias Target
or
//ftl:typealias
type Alias = Target
eg.
//ftl:typealias
type UserID string
//ftl:typealias
type UserToken = string
Optional types
FTL supports optional types, which are types that can be None
or Some
and can be declared via ftl.Option[T]
. These types are provided by the ftl
runtimes. For example, the following FTL type declaration in go, will provide an optional string type "Name":
type EchoResponse struct {
Name ftl.Option[string] `json:"name"`
}
The value of this type can be set to Some
or None
:
resp := EchoResponse{
Name: ftl.Some("John"),
}
resp := EchoResponse{
Name: ftl.None(),
}
The value of the optional type can be accessed using Get
, MustGet
, or Default
methods:
// Get returns the value and a boolean indicating if the Option contains a value.
if value, ok := resp.Name.Get(); ok {
resp.Name = ftl.Some(value)
}
// MustGet returns the value or panics if the Option is None.
value := resp.Name.MustGet()
// Default returns the value or a default value if the Option is None.
value := resp.Name.Default("default")
Unit "void" type
The Unit
type is similar to the void
type in other languages. It is used to indicate that a function does not return a value. For example:
//ftl:ingress GET /unit
func Unit(ctx context.Context, req builtin.HttpRequest[ftl.Unit, ftl.Unit, TimeRequest]) (builtin.HttpResponse[ftl.Unit, string], error) {
return builtin.HttpResponse[ftl.Unit, string]{Body: ftl.Some(ftl.Unit{})}, nil
}
This request will return an empty body with a status code of 200:
curl http://localhost:8891/unit -i
HTTP/1.1 200 OK
Date: Mon, 12 Aug 2024 17:58:22 GMT
Content-Length: 0
Builtin types
FTL provides a set of builtin types that are automatically available in all FTL runtimes. These types are:
builtin.HttpRequest[Body, PathParams, QueryParams]
- Represents an HTTP request with a body of typeBody
, path parameter type ofPathParams
and a query parameter type ofQueryParams
.builtin.HttpResponse[Body, Error]
- Represents an HTTP response with a body of typeBody
and an error of typeError
.builtin.Empty
- Represents an empty type. This equates to an empty structure{}
.builtin.CatchRequest
- Represents a request structure for catch verbs.