Generics

Why This Matters

Generics let you reuse logic without sacrificing compile-time type guarantees.

Core Idea

Write one definition that works for many concrete types.

Current scope:

  • user-defined generic functions/classes/interfaces are supported
  • user-defined generic enums are not supported yet

Generic Functions

function identity<T>(value: T): T {
    return value;
}

function main(): None {
    a: Integer = identity<Integer>(10);
    return None;
}

Type arguments can often be inferred when context is strong enough.

Generic Classes

class Box<T> {
    value: T;

    constructor(value: T) {
        this.value = value;
    }

    function get(): T {
        return this.value;
    }
}

Generic Interfaces

interface Reader<T> {
    function read(): T;
}

Constraints (extends)

Use interface bounds to require capabilities:

import std.io.*;

interface Named { function name(): String; }

function printName<T extends Named>(value: T): None {
    println(value.name());
    return None;
}

Bounds are interface-based; invalid/unknown/non-interface bounds are rejected.

Nested Generic Types

Generic types compose naturally:

  • Option<List<Integer>>
  • Result<Map<String, Integer>, String>

Practical Guidance

  • add generic parameters only when reusability is real
  • keep bounds minimal and meaningful
  • prefer explicit type args when readability is improved

Example

Built and maintained by TheRemyyy. Arden is open source under Apache 2.0 and published at theremyyy.dev.