Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type Aliases

Type aliases introduce a new name for an existing type. They improve code readability by giving domain-specific names to generic or primitive types without changing the underlying representation.

Syntax

A type alias is declared with the type keyword (no trailing ;), inside an entity or at program scope:

entity Token {
    type Amount = U256
    type Timestamp = u64
}

After declaration, the alias can be used in place of the original type. The two names are interchangeable: a U256 parameter or a literal can be assigned to an Amount member and vice versa.

Usage

Aliases make member declarations, route signatures, and record fields more expressive:

entity Token {
    type Amount = U256

    record Transfer {
        sender: address,
        recipient: address,
        value: Amount
    }

    routes {
        mint(to: address, amount: Amount) => []

        transfer(to: address, amount: Amount)
            where m_balances[msg::sender] >= amount : throw 100
        => []
    }

    m_total_supply: Amount {
        in mint(_, amount) => m_total_supply + amount
    }

    m_balances: HashMap<address, Amount> {
        in mint(to, amount) => m_balances.insert(to, m_balances[to] + amount)
        in transfer(to, amount) => m_balances
            .insert(msg::sender, m_balances[msg::sender] - amount)
            .insert(to, m_balances[to] + amount)
    }
}

Aliases for Complex Types

Aliases are particularly valuable when the underlying type is verbose:

type Approvals = HashMap<address, HashMap<address, U256>>
type Voters = Vec<address>
type PriceOracle = Address<Oracle>

Without aliases, these types would need to be repeated in full wherever they appear, making the code harder to read and maintain.

Scope

Type aliases declared inside an entity are scoped to that entity. They are not visible in other entities within the same file. Declare an alias at program scope (outside any entity) to share it between entities.

Aliases vs. Newtypes

Type aliases are transparent – two aliases of the same type are not distinguished. This means you cannot use aliases to prevent accidental mixing of conceptually different values:

type UserId = u64
type ProductId = u64

// Accepted: both names stand for u64.
pure fn as_product(user: UserId) -> ProductId {
    user
}

If you need distinct types that the compiler will not conflate, consider using single-field records instead:

record UserId { value: u64 }
record ProductId { value: u64 }