Skip to main content

Type Checking

Types can be assigned or cast to different types so long as they have the same structure. However, sometimes you need to distinguish between and narrow types at runtime. This is when type checking comes in.

Type checks have the following form:

value is Type

They emit the code required to check the type at runtime, and return a Bool value.

Structure

If you have a value of type Any, you can determine whether it's an atom or a pair.

For example:

fun count_atoms(value: Any) -> Int {
if value is Bytes {
1
} else {
let first = count_atoms(value.first);
let rest = count_atoms(value.rest);
first + rest
}
}

Length

You can check against a type with a fixed length:

fun calculate_coin_id(
parent_coin_info: Bytes,
puzzle_hash: Bytes,
amount: Int,
) -> Bytes32 {
assert parent_coin_info is Bytes32;
assert puzzle_hash is Bytes32;
sha256(parent_coin_info + puzzle_hash + amount as Bytes)
}

Values

You can even check against a specific integer value:

let num: Any = 42;
assert num is 42;

Although if you have an Int already, you may as well just do a simple equality check:

let num = 42;
assert num == 42;

Complex Checks

You can check against more complicated nested types as well:

struct Point {
x: Int,
y: Int,
}

let value: Any = 42;
assert !(value is Point);

Union Narrowing

If you have a union of one or more values, you can check if it's one of the items in the union. This will narrow the type if it's not.

let value: Bytes32 | nil = nil;

if !(value is nil) {
// value must be Bytes32
}

Recursive Checks

You can check against recursive types only if it would disambiguate a union:

let list: List<Int> = [1, 2, 3];

assert value is (Int, List<Int>);

However, if you were to try to do this, it would fail since it's a recursive type:

let value: Any = 42;

assert value is List<Int>; // Type error

To achieve this, you can write your own recursive function to check instead:

fun is_int_list(value: Any) -> Bool {
if value is Bytes {
return value == nil;
}
value.first is Int && is_int_list(value.rest)
}