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