---
schema_version: "1"
id: 9837a20363f3d0b9ff0f240f4b5e0a754977417e2bc86a23d67545b39163e411
title: Type System
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/dataweave/2.6/dataweave-type-system.md
canonical_url: https://docs.mulesoft.com/dataweave/2.6/dataweave-type-system
source_site: docs.mulesoft.com
content_type: documentation
content_hash: c709b93af65b70beea1fae49afd359a354c0fd95a11014f2a866572a25f0bb0a
description: MuleSoft Documentation Site
release: "2.6"
latest: false
---
---
product: DataWeave
version: 2.6
---

# Type System

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

2.x versions of DataWeave support a type system. To take advantage of the type-checking that the
type system executes, you need to provide constraint expressions for variables and functions
described in this section. For information about how values for these types are defined, refer to
[Value Constructs for Types](https://docs.mulesoft.com/dataweave/2.6/dataweave-types).

A type system defines a set of constraints to a set of constructs, such as:

- Variables

- Function parameters

These constraints are used in the type-checking phase, when DataWeave ensures that the values
assigned to variables or the arguments for a function call respect its constraints, for example:

DataWeave Script:

%dw 2.0 import \* from dw::core::Strings output application/json

var userName: String = "John"

The variable definition for `userName` has the constraint of assigning a value of type `String`. If
some other value type is assigned, a type-checking error is raised.

DataWeave Script:

%dw 2.0 import \* from dw::core::Strings output application/json

fun toUser(id: Number, userName: String): String = "you called the function toUser!"

The constraints to call the function `toUser` are that the first argument has to be of type
`Number`, the second one of type `String` (to be coercible to those types). Another constraint is
that the result of the function has to be of type `String`. This constraint isn’t used in the call
for `toUser`; it’s applied to its definition to validate that the function body generates the proper
type.

toUser(123, "John") toUser("123", true)

Although you might expect the second call to fail, autocoercion enables the call to be successful,
and both calls work. In the case of the second function call, there is autocoercion of the `String`
value `"123"` to the `Number` value `123`, and the `Boolean` value `true` to the `String` value
`"true"`, which makes it possible to call the function.  
An example of a call that throws a type-checking error is `toUser("a 12", "John")`, because the
String value `"a 12"` isn’t coercible to a `Number` type.

DataWeave also uses a global type inference algorithm to validate your code even if no types are
specified as constraints.

> [!NOTE] Although the use of constraints is optional, they can be useful in big scripts or multiple
> scripts. The type system helps you to avoid bugs in your DataWeave logic because it causes the
> type-checking algorithm to run. Additionally, when you write your script in an IDE and define
> these constraints, the tooling helps you to find type checking errors, instead of when the script
> is running and fails.

The types supported by the DataWeave type system are divided into three categories:

- Simple Types

- Composite Types

- Complex Types

## Simple Types

Simple types represent values such as strings, Booleans, and so on. These values are atomic; they
are not composed of other values. These are the simple types:

- `String`

- `Boolean`

- `Number`

- `Regex`

- `Null`

- Temporal: `Date`, `DateTime`, `LocalDateTime`, `LocalTime`, `Time`, `Period`

### Null

`Null` is a type of only one value, the value `null`, which means that `null` cannot be assigned to
the type `String` or any other type except for the type `Null`.

For example, the `repeat` function in the String module has the signature
`repeat(String, Number): String`, which means that the function accepts as a first parameter only a
value of type `String`, and as a second parameter only a value of type `Number.` The function
returns a value of type `String`.

DataWeave Script:

%dw 2.0 import \* from dw::core::Strings output application/json
---

repeat("a", 3)

This returns `"aaa"`, but the following example throws an error because the value `null` cannot be
assigned to the parameter that expects a value of type `String`:

DataWeave Script:

%dw 2.0 import \* from dw::core::Strings output application/json
---

repeat(null, 3)

In the following example, the script assigns to the first parameter a value that is the type `Null`
(the type of this value is `Type<Null>`). It returns `"NullNullNull"` because autocoercion coerces
the value to the type `String` (`"Null"`).

DataWeave Script:

%dw 2.0 import \* from dw::core::Strings output application/json
---

repeat(Null, 3)

Some functions have an overloaded signature (the function has multiple definitions for different
parameter types) that let you call it with `null`.

For example, the `isNumeric` function from `dw::core::Strings` has the signature
`isNumeric(String): Boolean`, which receives a string and successfully returns a result if that
string is numeric, but the function is also defined as `isNumeric(Null): Boolean`.

So, if you call the function `isNumeric` with `null` (`isNumeric(null)`), the function does not
throw an exception. At runtime, the function that is dispatching algorithm selects the correct
function based on the types of the values you use. The function returns `false` because of the
definition of `isNumeric` for `null` as the argument.

## Composite Types

A composite type contains other values. The composite types are `Array`, `Object` and `Function`.

### Array Type

An array is of the type `Array<T>` in which `T` is a type parameter that defines the type of the
elements inside the array. For example, the syntax to define a variable with the type `Array` of
`Number` is:

var idsList: Array<Number> = \[1, 22, 333, 4444\]

The variable `idsList` passes the type-checking phase only when the array that is assigned to it
only contains values of the `Number` type.

### Object Type

You can define an `Object` type in two ways: `Object` or `{}`. Both define an open object and don’t
specify any constraint to their key-value pairs. See also
[Close and Open Objects](#close_open_objects).

The syntax for defining an `Object` type with a set of constraints for its key-value pairs is very
similar to the syntax for defining the value of an `Object` type:

{ keyName @(attrName: AttrType): valueType, ... }

For example, the syntax to define a `User` type with `firstName` `String`, `lastName` `String`, and
`age` `Number` is:

DataWeave Script:

%dw 2.0 output application/json

type User = { firstName: String, lastName: String, age: Number }

You can apply modifiers to each key-value pair to specify when a field is always present or when a
field can be repeated.

For repeated fields use `*`. For example, the following type allows you to have multiple `lastName`
fields:

DataWeave Script:

%dw 2.0 output application/json

type User = { firstName: String, lastName\*: String, age: Number }

For conditional fields, use `?`. For example, the following type allows the `age` field to be
present or not:

DataWeave Script:

%dw 2.0 output application/json

type User = { firstName: String, lastName\*: String, age?: Number }

#### Close and Open Objects

`Object` type can be either closed or open. A _closed_ object accepts an object value only if there
are no fields except the key-value pairs specified by the type.

An _open_ object only put constraints on the fields that are declared in the type, and if they are
all verified, then the type accepts the value. The type accepts objects that have other fields apart
of the ones mentioned in the declaration. All `object` types are open unless specified.

The following example succeeds even if `age` is not in the type declaration because the type of the
variable `user` is an open object:

DataWeave Script:

%dw 2.0 output application/json

var user: {firstName: String, lastName: String} = {firstName: "John", lastName: "Smith", age: 34}

The syntax to specify a closed object is `{| |}`. The following example makes the `User` type
support only the keys `firstName` and `lastName`. The script throws an exception because the `age`
field is not accepted.

DataWeave Script:

%dw 2.0 output application/json

var user: {|firstName: String, lastName: String|} = {firstName: "John", lastName: "Smith", age: 34}

### Function Type

DataWeave is a functional language, and functions are considered first class citizens, which means
that functions are values with associated types.

The syntax to define a function type is:

(paramType: ParamType,...) -> ReturnType

For example, if you want to define in a constraint a `Function` type that has a parameter of type
`String`, a second parameter of type `Number`, and a `Boolean` return value, the correct syntax is:

(paramA: String, paramB: Number) -> Boolean

In the following example, you define a function that receives another function as an argument:

DataWeave Script:

%dw 2.0 output application/json

fun applyIDsChange(ids: Array<Number>, changeTo: (Number) -> Number): Array<Number> = ???

If you call the function `applyIDsChange` with a function that does not match the `changeTo`
constraint `(Number) → Number`, DataWeave throws a type-checking error.

For example, the following call works because `abs` is a function that takes a value of the `Number`
type and returns a `Number`, which matches the `changeTo` parameter:

applyIDsChange(\[1,-6, 3, -8\], abs)

But the following call fails because `sum` is a function that takes an `Array` and returns a
`Number`, so it does not match the parameter constraint:

applyIDsChange(\[1,-6, 3, -8\], sum)

## Complex Types

Complex types include the `Any` and `Nothing` types, the `Union` type, the `Intersection` type, and
`Literal` types, each of which is named intuitively.

### Any and Nothing

In some cases, you cannot enforce a restriction because the type accepts all the value:

- `Any` type accepts all possible values.

- `Nothing` type accepts no value, but it can be assigned to all the types. This type is not
  frequently used explicitly, but it is used by the type inference algorithm.

### Union Type

The `Union` type is used to compose types. The syntax to define a `Union` type is:

TypeA | TypeB | ...

The following example defines a variable with a constraint that accepts a value of type `String` or
`Number`:

var age: String | Number = if (payload.allStrings) "32" else 32

A common pattern is to use `Null` type with a `Union` type to specify that a type accepts `null` as
a value. In the following example, the function `parseEmail` allows inputs of type `String` or
`Null`. In this case, you can have a object with a payload optional field `email` and you call the
function with `payload.email`.

fun parseEmail(email: String | Null) = "Code that handles email being of type String or Null"

### Intersection Type

_Introduced in DataWeave 2.3.0. Supported by Mule 4.3 and later._

The `Intersection` type intersects `Object` types. In this case, the intersection works as the
concatenation (`++`) of object types.

The syntax for the `Intersection` type is:

TypeA & TypeB & ...

In the following example, the `Intersection` concatenates the two `Object` types, resulting in the
type `{name: String, lastName: String}`. The type is an open object that can accept additional
key-value pairs. The variable accepts the value assigned to it:

var a: {name: String} & {lastName: String} = {name: "John", lastName: "Smith", age: 34}

In the case of closed objects, it returns the concatenation of the object types but results in a
closed object.  
In the following example, the intersection results in the type `{|name: String, lastName: String|}`,
which throws an exception because a closed object does not accept an `Object` value if there are
additional fields in the object (field `age`):

var a: {|name: String|} & {|lastName: String|} = {name: "John", lastName: "Smith", age: 34}

### Literal Types

_Introduced in DataWeave 2.3.0. Supported by Mule 4.3 and later._

A literal type represents exactly one value. For example, the `String` value `"foo"` can be
represented with the type `"foo"`.

The following literal types are included to the type system:

- `String` literal types

- `Number` literal types

- `Boolean` literal types

You can use literal types with `Union` types to declare a type as a finite set of allowed values.
For example, the following type declarations are aliases of `Union` and literal types:

type Weekdays = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" type Days = Weekdays |
"Saturday" | "Sunday"

In the following example, the variable accepts only a value of the literal types `404` and `500`.
The type system ensures before runtime that the variable can be only one of those literal values:

DataWeave Script:

%dw 2.0 output application/json

var errorStatusCode: 404 | 500 = payload.statusCode match { case "error 404" -> 404 case "error 500"
-> 500 }

Function overloading enables you to define different behaviors based on the input argument’s value:

DataWeave Script:

%dw 2.0 import \* from dw::core::Strings output application/json

fun errorHandling(errorCode: 404 | 405, response): String = "Code for error 4XX handling here!" fun
errorHandling(errorCode: 500 | 501, response): String = "Code for error 5XX handling here!"
---

errorHandling(payload.statusCode, payload)

At runtime, the function-dispatching algorithm selects the correct function based on the type of the
value of `payload.statusCode`. It is not necessary to check the value of an argument with an `if`
statement to change the behavior of the function.

### Type Parameters

A type parameter enables you to write a function or data type generically so that you can handle
values identically, without depending on the type of the values.

For example, you can define a function that returns the first element of an array without losing its
type information. In the example, the variable definitions `firstString:String` and
`firstNumber:Number` specify the type of the item in the array that the `head` function takes as
input.

```DataWeave
%dw 2.0
fun head<ItemType>(elements: Array<ItemType>): ItemType = elements[0]!

var firstString:String = head(["DataWeave", "Java", "Scala", "Haskell"]) ++ " Rules!!!"
var firstNumber:Number = head([1,2,3])
output application/json
---
firstNumber
```

In the body of the script, `firstNumber` returns the number `1`. If you replace `firstNumber` with
`firstString`, the script returns the string `"DataWeave Rules!!!"`.

#### Binding Type Parameters

You can bind type parameters to require a value of a specific type. Appending `{name: "DataWeave"}`
in the following example is valid because `{name: String}` in the function definition indicates that
the value of the `name` key must be a string.

```DataWeave
%dw 2.0

fun addName<User <: {} >(user: User): User & {name: String} = user ++ {name: "DataWeave"}

var myUser: {name: String, developers: Number} = addName({developers: 3})
```

#### Parameterizing Type Definitions

You can use type parameters to parameterize type definitions. For example, assume that you define a
data structure that models file content, one for text files and the other for binary files. You can
use type parameters to construct new types that dispatch the correct implementation.

```DataWeave
%dw 2.0

type FileData<Content> = {
    data: Content,
    name: String
}

fun read(file: FileData<String>) =  "This is a text file with data " ++ file.data
fun read(file: FileData<Binary>) =  "This is a binary file with data " ++ (file.data as String {base: "64"})

---
{
  binary: read({data: "Hello World" as Binary, name: "myFile.bin"}),
  text: read({data: "Hello World", name: "myFile.txt"})
}
```

## Reuse Types

You can declare and use types within the same DataWeave script (see
[Type System](https://docs.mulesoft.com/dataweave/2.6/dataweave-type-system)), or you can reuse types from different sources by loading them
with a specific module loader. DataWeave currently supports loading types from:

- [Reusing Types from DataWeave Modules](https://docs.mulesoft.com/dataweave/2.6/dataweave-type-reuse-modules)

- [Reusing Types from a JSON Schema](https://docs.mulesoft.com/dataweave/2.6/dataweave-type-reuse-json-schema)

- [Reusing an XML Schema](https://docs.mulesoft.com/dataweave/2.6/dataweave-type-reuse-xml-schema)

- [Reusing Types from Java Classes](https://docs.mulesoft.com/dataweave/2.6/dataweave-type-reuse-java-classes)

Module loaders are used to load files as DataWeave modules, in which different parts of those files
are loaded as DataWeave functions, variables, types, and namespace definitions. Using a prefix such
as `java!` or `xmlschema!` in the import directive tells DataWeave which module loader to use when
loading the Java class or the XML schema as a DataWeave module.
