Skip to main content

WIT Type Mapping

This document describes how WebAssembly Interface Types (WIT) map to and from Morphir's Intermediate Representation (IR).

Overview​

Morphir's WIT integration provides bidirectional type mapping:

  • WIT -> IR (make): Converts WIT source to Morphir's domain types
  • IR -> WIT (gen): Converts Morphir domain types back to WIT source

The mapping preserves semantic meaning while adapting to each representation's conventions.

Primitive Types​

WIT primitive types map directly to Morphir primitive types:

WIT TypeMorphir TypeDescription
boolBoolBoolean value
u8U8Unsigned 8-bit integer
u16U16Unsigned 16-bit integer
u32U32Unsigned 32-bit integer
u64U64Unsigned 64-bit integer
s8S8Signed 8-bit integer
s16S16Signed 16-bit integer
s32S32Signed 32-bit integer
s64S64Signed 64-bit integer
f32F3232-bit floating point
f64F6464-bit floating point
charCharUnicode character
stringStringUTF-8 string

Example:

interface primitives {
type age = u8;
type name = string;
type active = bool;
}

Container Types​

List​

WIT lists map to Morphir list types:

WITMorphir
list<T>ListType{Element: T}

Example:

interface collections {
type numbers = list<u32>;
type names = list<string>;
}

Option​

WIT options map to Morphir option types:

WITMorphir
option<T>OptionType{Inner: T}

Example:

interface nullable {
type maybe-name = option<string>;
type maybe-age = option<u32>;
}

Result​

WIT results map to Morphir result types:

WITMorphir
resultResultType{Ok: nil, Err: nil}
result<T>ResultType{Ok: T, Err: nil}
result<T, E>ResultType{Ok: T, Err: E}
result<_, E>ResultType{Ok: nil, Err: E}

Example:

interface errors {
type error-code = u32;
type parse-result = result<string, error-code>;
type void-result = result<_, error-code>;
}

Tuple​

WIT tuples map to Morphir tuple types:

WITMorphir
tuple<T1, T2, ...>TupleType{Types: [T1, T2, ...]}

Example:

interface pairs {
type point = tuple<f32, f32>;
type named-value = tuple<string, u32, bool>;
}

Composite Types​

Record​

WIT records map to Morphir record definitions:

WIT:

record user {
id: string,
name: string,
age: u32,
active: bool,
}

Morphir Domain:

TypeDef{
Name: "user",
Kind: RecordDef{
Fields: []Field{
{Name: "id", Type: PrimitiveType{String}},
{Name: "name", Type: PrimitiveType{String}},
{Name: "age", Type: PrimitiveType{U32}},
{Name: "active", Type: PrimitiveType{Bool}},
},
},
}

Variant​

WIT variants map to Morphir variant definitions:

WIT:

variant status {
pending,
active(string),
completed(u32),
}

Morphir Domain:

TypeDef{
Name: "status",
Kind: VariantDef{
Cases: []VariantCase{
{Name: "pending", Payload: nil},
{Name: "active", Payload: &PrimitiveType{String}},
{Name: "completed", Payload: &PrimitiveType{U32}},
},
},
}

Enum​

WIT enums map to Morphir enum definitions:

WIT:

enum color {
red,
green,
blue,
}

Morphir Domain:

TypeDef{
Name: "color",
Kind: EnumDef{
Cases: []Identifier{"red", "green", "blue"},
},
}

Flags​

WIT flags map to Morphir flags definitions:

WIT:

flags permissions {
read,
write,
execute,
}

Morphir Domain:

TypeDef{
Name: "permissions",
Kind: FlagsDef{
Flags: []Identifier{"read", "write", "execute"},
},
}

Type Alias​

WIT type aliases map to Morphir type alias definitions:

WIT:

type user-id = string;
type timestamp = u64;

Morphir Domain:

TypeDef{
Name: "user-id",
Kind: TypeAliasDef{
Target: PrimitiveType{String},
},
}

Resource Types​

WIT resources and handles map to Morphir resource and handle types:

Resource Definition​

WIT:

resource file {
constructor(path: string);
read: func() -> result<list<u8>, error-code>;
write: func(data: list<u8>) -> result<_, error-code>;
}

Morphir Domain:

TypeDef{
Name: "file",
Kind: ResourceDef{
Constructor: &Constructor{
Params: []Param{{Name: "path", Type: PrimitiveType{String}}},
},
Methods: []ResourceMethod{
{Name: "read", Function: ...},
{Name: "write", Function: ...},
},
},
}

Handle Types​

WITMorphir
own<resource>HandleType{Resource: "resource", IsBorrow: false}
borrow<resource>HandleType{Resource: "resource", IsBorrow: true}

Example:

interface files {
resource file;

open: func(path: string) -> own<file>;
read: func(f: borrow<file>) -> list<u8>;
}

Functions​

WIT functions map to Morphir function definitions:

WIT:

interface math {
add: func(a: s32, b: s32) -> s32;
divide: func(a: s32, b: s32) -> result<s32, string>;
log: func(message: string);
}

Morphir Domain:

Function{
Name: "add",
Params: []Param{
{Name: "a", Type: PrimitiveType{S32}},
{Name: "b", Type: PrimitiveType{S32}},
},
Results: []Type{PrimitiveType{S32}},
}

Multiple Return Values​

Functions with multiple return values use tuple-style results:

WIT:

interface multi {
get-pair: func() -> (string, u32);
}

Packages and Interfaces​

Package Structure​

WIT packages map to Morphir package structures:

WIT:

package example:http@1.0.0;

interface types {
type url = string;
}

interface client {
use types.{url};
get: func(u: url) -> result<string, string>;
}

Morphir Domain:

Package{
Namespace: "example",
Name: "http",
Version: semver("1.0.0"),
Interfaces: []Interface{
{Name: "types", Types: [...]},
{Name: "client", Functions: [...]},
},
}

Worlds​

WIT worlds map to Morphir world definitions:

WIT:

world http-server {
import types;
export handler;
}

Naming Conventions​

WIT uses kebab-case for all identifiers. The mapping preserves these conventions:

WITMorphir Identifier
user-iduser-id
http-clienthttp-client
get-user-by-idget-user-by-id

Escaped Identifiers​

WIT supports escaped identifiers using % prefix for reserved words:

interface reserved {
type %type = string;
%import: func();
}

Documentation​

WIT documentation comments (///) are preserved in Morphir:

WIT:

/// A user in the system
/// with unique identifier
record user {
/// The unique user ID
id: string,
/// Display name
name: string,
}

Morphir Domain:

TypeDef{
Name: "user",
Docs: Documentation{Lines: ["A user in the system", "with unique identifier"]},
Kind: RecordDef{
Fields: []Field{
{Name: "id", Docs: Documentation{Lines: ["The unique user ID"]}},
{Name: "name", Docs: Documentation{Lines: ["Display name"]}},
},
},
}

Future Types (WASI Preview 3)​

The following types are planned for WASI Preview 3 and have preliminary support:

Future​

WITMorphir
futureFutureType{Inner: nil}
future<T>FutureType{Inner: T}

Stream​

WITMorphir
streamStreamType{Element: nil}
stream<T>StreamType{Element: T}

Unsupported Features​

Some WIT features are not yet fully supported:

  • Complex use paths with versioning
  • Resource methods (constructor, methods, statics) - basic support only
  • World imports/exports - structural only
  • Inline interface definitions in worlds

These features are tracked for future implementation.

Round-Trip Validation​

When using morphir wit build, the system validates that:

  1. WIT source parses correctly
  2. Morphir IR is generated successfully
  3. Generated WIT is semantically equivalent to original

A successful round-trip indicates the type mapping preserved all semantic information.

See Also​