Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 218 additions & 39 deletions en/docs/develop/integration-artifacts/supporting/types.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Types
description: Define shared data structures with record types, enums, union types, and table types for type-safe integrations.
description: Define shared data structures with record, enum, service class, union, and array types for type-safe integrations.
---

import Tabs from '@theme/Tabs';
Expand All @@ -10,6 +10,8 @@ import TabItem from '@theme/TabItem';

Type artifacts define the data structures used throughout your integration. They ensure type safety across services, event handlers, and transformations. Define types in dedicated `.bal` files and reuse them across all artifacts in your project.

The visual designer exposes five type kinds: **Record**, **Enum**, **Service Class**, **Union**, and **Array**. Each kind maps to a Ballerina type definition in source.

## Adding a type

<Tabs>
Expand All @@ -21,16 +23,16 @@ Type artifacts define the data structures used throughout your integration. They

2. Click **+** next to **Types** in the sidebar (or click **+ Add Type** from the Types canvas).

3. In the **New Type** panel, choose **Create from scratch** or **Import**.
3. In the **New Type** panel, choose **Create from scratch** or **Import** to bring in an existing definition.

![New Type creation form showing Kind and Name fields](/img/develop/integration-artifacts/supporting/types/step-2.png)

| Field | Description |
|---|---|
| **Kind** | The type kind: **Record**, **Enum**, **Union**, or **Table**. |
| **Kind** | The type kind: **Record**, **Enum**, **Service Class**, **Union**, or **Array**. |
| **Name** | A unique name for the type (for example, `OrderRequest`). |
| **Fields** | For records — add fields using the **+** button. Each field has a name and a type. |
| **Advanced Options** | Expand to set additional constraints such as closed record enforcement. |
| **Members / Fields / Resource Methods** | The structural members for the selected kind. The label changes to match the kind. |
| **Advanced Options** | Per-kind options such as **Allow Additional Fields**, **Is Readonly Type**, and **Accessible by Other Integrations**. |

4. Click **Save**. The type is added to your project and appears in the type diagram.

Expand Down Expand Up @@ -95,64 +97,227 @@ type OrderRequest record {|

## Type kinds

### Records
### Record

A record defines a structured type with named fields.

<Tabs>
<TabItem value="ui" label="Visual Designer" default>

Select **Record** from the **Kind** dropdown to define a structured type with named fields. Use **Advanced Options** to enforce a closed record (no extra fields allowed).
Select **Record** from the **Kind** dropdown, then add one row per field using **+**.

For each field:

| Control | Description |
|---|---|
| **Name** | The field name. |
| **Type** | The field type (built-in, user-defined, or another record). |
| **Inline record** (`{}`) | Define the field's type as a nested record inline, instead of referencing an existing type. |
| **Optional** (`?`) | Mark the field optional. The field becomes `T?` and may be absent at runtime. |
| **Delete** (trash) | Remove the field. |

Expand a field row to set:

| Option | Description |
|---|---|
| **Default Value** | A literal expression assigned when the field is omitted. The field is then defaultable in source. |
| **Description** | Documentation for the field, emitted as a Ballerina doc comment. |
| **Readonly** | Mark this field immutable. The field becomes `readonly T`. |

**Advanced Options**:

| Option | Description |
|---|---|
| **Allow Additional Fields** | Generate an open record (`record { ... }`) that accepts unknown fields. Leave unchecked for a closed record (`record {\| ... \|}`). |
| **Is Readonly Type** | Wrap the whole type as `readonly & T` so every field is immutable. |
| **Accessible by Other Integrations** | Add the `public` qualifier so the type can be imported from other packages. |

</TabItem>
<TabItem value="code" label="Ballerina Code">

```ballerina
// Closed record — no extra fields permitted
type OrderRequest record {|
string customerId;
# Represents an order placed by a customer.
public type OrderRequest record {|
# Unique identifier of the customer.
readonly string customerId;
LineItem[] items;
Address shippingAddress;
# Optional discount coupon.
string? couponCode;
string currency = "USD";
|};
```

</TabItem>
</Tabs>

### Enums
### Enum

An enum defines a fixed set of named string values.

<Tabs>
<TabItem value="ui" label="Visual Designer" default>

Select **Enum** from the **Kind** dropdown to define a fixed set of string values. Add each member value using the **+** button in the **Members** section.
Select **Enum** from the **Kind** dropdown, then add each member using **+**.

For each member:

| Control | Description |
|---|---|
| **Enum member name** | The member identifier (for example, `PENDING`). |
| **Constant Expression** | The string value bound to the member. Leave empty to use the member name as the value. |

</TabItem>
<TabItem value="code" label="Ballerina Code">

```ballerina
enum OrderStatus {
PENDING,
CONFIRMED,
SHIPPED,
DELIVERED,
CONFIRMED = "confirmed",
SHIPPED = "shipped",
DELIVERED = "delivered",
CANCELLED
}
```

</TabItem>
</Tabs>

### Unions
### Service class

A service class defines an object that exposes resource methods, used to model dynamically generated services such as GraphQL resolvers.

<Tabs>
<TabItem value="ui" label="Visual Designer" default>

Select **Union** from the **Kind** dropdown to allow a value to be one of several types. Add each member type using the **+** button.
#### Create a service class

Select **Service Class** from the **Kind** dropdown, then add one row per resource method using **+**.

For each resource method:

| Control | Description |
|---|---|
| **Name** | The resource path/name (for example, `name1`). |
| **Type** | The return type of the resource method. |
| **+ Add Parameter** | Add an input parameter. Each parameter takes a **Parameter Name**, **Parameter Type**, and an optional **Default Value**. |
| **Delete** (trash) | Remove the resource method. |

#### Edit the service class

The editing experience for a service class differs from other kinds. Click **Edit** on the type to open the **Edit Type: Service Class** panel:

| Control | Description |
|---|---|
| **Object Name** | Rename the service class. |
| **Description** | Free-text documentation rendered as a Ballerina doc comment. |
| **Fields** | List of resource methods. Use **+** to add, the pencil icon to edit a field, or the trash icon to remove it. |
| **Implement** | Switch to the **Service Class Designer** to add class variables and write method bodies. |

#### Edit a field

Click the pencil icon on a field to open the **Edit Field** panel:

| Control | Description |
|---|---|
| **Field Name** | The resource path/name. |
| **Description** | Documentation for the field. |
| **Arguments** | Use **+ Add Argument** to define input parameters for the resource method. |
| **Field Type** | The return type (for example, `string\|error`). |

Comment on lines +223 to +227
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and examine the content around lines 223-227
if [ -f "en/docs/develop/integration-artifacts/supporting/types.md" ]; then
  echo "=== File found. Content at lines 223-227 ==="
  sed -n '223,227p' "en/docs/develop/integration-artifacts/supporting/types.md" | cat -n
  echo ""
  echo "=== Broader context (lines 215-235) ==="
  sed -n '215,235p' "en/docs/develop/integration-artifacts/supporting/types.md" | cat -n
else
  echo "File not found at expected path"
fi

Repository: wso2/docs-integrator

Length of output: 1483


🏁 Script executed:

# Search for similar escape patterns with pipes in this file
echo "=== Searching for backslash-escaped pipes in the file ==="
rg '\\\\\\|' en/docs/develop/integration-artifacts/supporting/types.md

Repository: wso2/docs-integrator

Length of output: 13225


🏁 Script executed:

# Check file size to understand its scope
wc -l en/docs/develop/integration-artifacts/supporting/types.md

Repository: wso2/docs-integrator

Length of output: 126


Use HTML entity &#124; instead of backslash-escaped pipe in inline code.

In the "Edit a field" table, the return type example uses string\|error. When backslash-escaped pipes appear inside inline code blocks within Markdown tables, they may render as visible backslashes depending on the Markdown processor. Use the HTML entity &#124; instead, which consistently renders as | without backslashes.

Proposed change
-| **Field Type** | The return type (for example, `string\|error`). |
+| **Field Type** | The return type (for example, `string&#124;error`). |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@en/docs/develop/integration-artifacts/supporting/types.md` around lines 223 -
227, Replace the backslash-escaped pipe inside the inline code example for the
"Field Type" cell: locate the table row containing "**Field Type**" and the
example `string\|error` and change the inline code to use the HTML entity for
pipe (e.g., `string&#124;error`) so the pipe displays correctly without a
visible backslash.

Expand **Advanced Configurations** to set:

| Option | Description |
|---|---|
| **Field Configuration** | Free-form JSON configuration such as field-level cache settings. |
| **Request Context** | Inject a context value used to pass meta-information among GraphQL resolvers. |
| **Field Metadata** | Inject the field metadata used to access information about the field in a GraphQL document. |

#### Service Class Designer

Click **Implement** to open the **Service Class Designer**, where you add class state and method implementations.

![Service Class Designer showing Class Variables and Methods sections](/img/develop/integration-artifacts/supporting/types/service-class-designer.png)

**Class Variables** — click **+ Variable** to open the **Add Variable** panel:

| Control | Description |
|---|---|
| **Variable Name** | The variable identifier. |
| **Variable Type** | The variable type. |
| **Default Value** | The initial value assigned at construction. |

**Methods** — click **+ Method** to open the **Add Method** panel. Choose the method kind from the dropdown — **resource**, **remote**, or **init** — then fill in:

| Control | Description |
|---|---|
| **Function Name** | The method name. Not shown for `init`. |
| **Description** | Documentation for the method. |
| **Parameters** | Use **+ Add Parameter** to add inputs (name, type, optional default value). |
| **Return Type** | The method return type. Not shown for `init`. |

Use the pencil and trash icons next to each existing method to edit or remove it.

</TabItem>
<TabItem value="code" label="Ballerina Code">

```ballerina
type PaymentMethod CreditCard|BankTransfer|DigitalWallet;
# Represents a pet shelter exposed through GraphQL.
public service class Shelter {
private final string name;
private final string location;
private int capacity;

function init(string name, string location, int capacity) {
self.name = name;
self.location = location;
self.capacity = capacity;
}

# Returns the shelter name.
resource function get name() returns string|error {
return self.name;
}

resource function get location() returns string {
return self.location;
}

resource function get capacity() returns int {
return self.capacity;
}

remote function updateCapacity(int newCapacity) returns int {
self.capacity = newCapacity;
return self.capacity;
}
}
```

</TabItem>
</Tabs>

### Union

A union allows a value to be one of several member types.

<Tabs>
<TabItem value="ui" label="Visual Designer" default>

Select **Union** from the **Kind** dropdown, then add each member type using **+**. Members can be built-in types or other named types.

**Advanced Options**:

| Option | Description |
|---|---|
| **Is Readonly Type** | Wrap the union as `readonly & T` so values are immutable. |
| **Accessible by Other Integrations** | Add the `public` qualifier so the type can be imported from other packages. |

</TabItem>
<TabItem value="code" label="Ballerina Code">

```ballerina
public type PaymentMethod CreditCard|BankTransfer|DigitalWallet;

type CreditCard record {|
string cardNumber;
Expand All @@ -175,43 +340,57 @@ type DigitalWallet record {|
</TabItem>
</Tabs>

### Tables
### Array

An array defines an ordered list of values of a single member type.

<Tabs>
<TabItem value="ui" label="Visual Designer" default>

Select **Table** from the **Kind** dropdown to define an in-memory keyed collection. Specify the row type and the key field.
Select **Array** from the **Kind** dropdown.

| Control | Description |
|---|---|
| **Type of the Array** | The member type (required). |
| **Size of the Array** | A fixed length. Leave empty for an unbounded array. |

**Advanced Options**:

| Option | Description |
|---|---|
| **Is Readonly Type** | Wrap the array as `readonly & T[]` so it cannot be mutated. |
| **Accessible by Other Integrations** | Add the `public` qualifier so the type can be imported from other packages. |

</TabItem>
<TabItem value="code" label="Ballerina Code">

```ballerina
type ProductTable table<Product> key(id);

type Product record {|
readonly string id;
string name;
decimal price;
int stock;
|};

// Usage
ProductTable products = table [
{id: "P001", name: "Widget", price: 9.99, stock: 100},
{id: "P002", name: "Gadget", price: 24.99, stock: 50}
];
// Unbounded array
public type LineItems string[];

Product? widget = products["P001"];
// Fixed-length array
type Coordinates float[3];
```

</TabItem>
</Tabs>

## Map types

The visual designer does not expose **Map** as a Kind. To model dynamic key/value data, define a record instead:

- For a known set of keys, use a closed record (`record {| ... |}`).
- For arbitrary string keys with a uniform value type, use an open record with **Allow Additional Fields** enabled.

If you are editing source directly, the equivalent Ballerina form is `map<T>` — for example, `map<string>` for a string-valued map. Types declared this way appear as opaque references in the type diagram.

## Best practices

| Practice | Description |
|---|---|
| **Closed records** | Use `record {\| ... \|}` to restrict fields to only those defined |
| **Dedicated files** | Keep type definitions in separate `types.bal` files |
| **Descriptive names** | Name types after their domain concept (for example, `OrderRequest`, not `Data`) |
| **Reuse across artifacts** | Define types once and import them in services, event handlers, and functions |
| **Closed records** | Leave **Allow Additional Fields** unchecked unless you actually need extra keys. Closed records catch typos at compile time. |
| **Dedicated files** | Keep type definitions in separate `types.bal` files and import them where needed. |
| **Descriptive names** | Name types after their domain concept (for example, `OrderRequest`, not `Data`). |
| **Reuse across artifacts** | Define types once and reference them from services, event handlers, and functions. |
| **Prefer Readonly over reassignment** | Mark fields or whole types **Readonly** for immutable data, instead of relying on convention. |
| **Use records instead of maps in the designer** | The designer cannot edit `map<T>` types. Model dynamic data as records (open records when keys are unknown). |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading