Interfaces
The information on this page is only applicable to Go and TypeScript SDKs. Interfaces are not currently supported in the Python SDK.
Declaration
- Go
- TypeScript
The Go SDK supports interfaces, which allow you to define Go-style interface definitions so that your module can accept arbitrary values from other modules without being tightly coupled to the concrete type underneath.
To use an interface, define a Go interface that embeds DaggerObject
and use
it in a function argument:
Here is an example of the definition of an interface Fooer
with a single function foo
:
package main
import (
"context"
)
type MyModule struct{}
type Fooer interface {
DaggerObject
Foo(ctx context.Context, bar int) (string, error)
}
func (m *MyModule) Foo(ctx context.Context, fooer Fooer) (string, error) {
return fooer.Foo(ctx, 42)
}
Functions defined in interface definitions must match the client-side API
signature style. If they return a scalar value or an array, they must accept a
context.Context
argument and return an error
return value. If they return a
chainable object value, they must not return an error
value, and they do not need
to include a context.Context
argument.
Note that you must also provide argument names, since they directly translate to the GraphQL field argument names.
The TypeScript SDK supports interfaces, which allow you to define a set of functions that an object must implement to be considered a valid instance of that interface. That way, your module can accept arbitrary values from other modules without being tightly coupled to the concrete type underneath.
To use an interface, use the TypeScript interface
keyword and use it
as a function argument:
Here is an example of the definition of an interface Fooer
with a single function foo
:
import { func, object } from "@dagger.io/dagger"
export interface Fooer {
// You can also declare it as a method signature (e.g., `foo(): Promise<string>`)
foo: (bar: number) => Promise<string>
}
@object()
export class MyModule {
@func()
async foo(fooer: Fooer): Promise<string> {
return await fooer.foo(42)
}
}
Functions defined in interface definitions must match the client-side API signature style:
- Always define
async
functions in interfaces (wrap the return type in aPromise<T>
). - Declare it as a method signature (e.g.,
foo(): Promise<string>
) or a property signature (e.g.,foo: () => Promise<string>
). - Parameters must be properly named since they directly translate to the GraphQL field argument names.
Implementation
Here is an example of a module Example
that implements the Fooer
interface:
- Go
- TypeScript
package main
import (
"context"
"fmt"
)
type Example struct{}
func (m *Example) Foo(ctx context.Context, bar int) (string, error) {
return fmt.Sprintf("number is: %d", bar), nil
}
import { func, object } from "@dagger.io/dagger"
export interface Fooer {
// You can also declare it as a method signature (e.g., `foo(): Promise<string>`)
foo: (bar: number) => Promise<string>
}
@object()
export class Example {
@func()
async foo(bar: number): Promise<string> {
return `number is: ${bar}`
}
}
Usage
Any object module that implements the interface method can be passed as an argument to the function that uses the interface.
Dagger automatically detects if an object coming from the module itself or one of its dependencies implements an interface defined in the module or its dependencies. If so, it will add new conversion functions to the object that implement the interface so it can be passed as argument.
Here is an example of a module that uses the Example
module defined above and
passes it as argument to the foo
function of the MyModule
object:
- Go
- TypeScript
package main
import (
"context"
)
type Usage struct{}
func (m *Usage) Test(ctx context.Context) (string, error) {
// Because `Example` implements `Fooer`, the conversion function
// `AsMyModuleFooer` has been generated.
return dag.MyModule().Foo(ctx, dag.Example().AsMyModuleFooer())
}
import { dag, func, object } from "@dagger.io/dagger"
@object()
export class Usage {
@func()
async test(): Promise<string> {
// Because `Example` implements `Fooer`, the conversion function
// `AsMyModuleFooer` has been generated.
return dag.myModule().foo(dag.example().asMyModuleFooer())
}
}