Examples Verified (100%)
Type Syntax Cheatsheet
A comprehensive quick reference guide for T-Ruby type syntax. Bookmark this page for easy access to all type annotations and syntax patterns.
Basic Types
| Type | Description | Example |
|---|---|---|
String | Text data | name: String = "Alice" |
Integer | Whole numbers | count: Integer = 42 |
Float | Decimal numbers | price: Float = 19.99 |
Boolean | Boolean values | active: Boolean = true |
Symbol | Immutable identifiers | status: Symbol = :active |
nil | Absence of value | value: nil = nil |
Any | Any type (avoid when possible) | data: Any = "anything" |
void | No return value | def log(msg: String): void |
Variable Annotations
# Variable with type annotation
name: String = "Alice"
age: Integer = 30
price: Float = 99.99
# Multiple variables
x: Integer = 1
y: Integer = 2
z: Integer = 3
# Type inference (type annotation optional)
message = "Hello" # Inferred as String
Function Signatures
# Basic function
def greet(name: String): String
"Hello, #{name}!"
end
# Multiple parameters
def add(a: Integer, b: Integer): Integer
a + b
end
# Optional parameters
def greet(name: String, greeting: String = "Hello"): String
"#{greeting}, #{name}!"
end
# Rest parameters
def sum(*numbers: Integer): Integer
numbers.sum
end
# Keyword arguments
def create_user(name: String, email: String, age: Integer = 18): Hash
{ name: name, email: email, age: age }
end
# No return value
def log(message: String): void
puts message
end
Union Types
| Syntax | Description | Example |
|---|---|---|
A | B | Either type A or B | String | Integer |
A | B | C | One of multiple types | String | Integer | Boolean |
T | nil | Optional type | String | nil |
T? | Shorthand for T | nil | String? |
# Union types
id: String | Integer = "user-123"
id: String | Integer = 456
# Optional values
name: String | nil = nil
name: String? = nil # Shorthand
# Multiple types
value: String | Integer | Boolean = true
# Function with union return type
def find_user(id: Integer): User | nil
# Returns User or nil
end
Array Types
# Array of specific type
names: Array<String> = ["Alice", "Bob"]
numbers: Array<Integer> = [1, 2, 3]
# Array of union types
mixed: Array<String | Integer> = ["Alice", 1, "Bob", 2]
# Nested arrays
matrix: Array<Array<Integer>> = [[1, 2], [3, 4]]
# Empty array with type
items: Array<String> = []
Hash Types
# Hash with specific key and value types
scores: Hash<String, Integer> = { "Alice" => 100, "Bob" => 95 }
# Symbol keys
config: Hash<Symbol, String> = { host: "localhost", port: "3000" }
# Union value types
data: Hash<String, String | Integer> = { "name" => "Alice", "age" => 30 }
# Nested hashes
users: Hash<Integer, Hash<Symbol, String>> = {
1 => { name: "Alice", email: "alice@example.com" }
}
Generic Types
# Generic function
def first<T>(arr: Array<T>): T | nil
arr[0]
end
# Multiple type parameters
def pair<K, V>(key: K, value: V): Hash<K, V>
{ key => value }
end
# Generic class
class Box<T>
@value: T
def initialize(value: T): void
@value = value
end
def get: T
@value
end
end
# Using generics
box = Box<String>.new("hello")
result = first([1, 2, 3]) # Type inferred
Type Aliases
# Simple alias
type UserId = Integer
type EmailAddress = String
# Union type alias
type ID = String | Integer
type JSONValue = String | Integer | Float | Boolean | nil
# Collection alias
type StringList = Array<String>
type UserMap = Hash<Integer, User>
# Generic alias
type Result<T> = T | nil
type Callback<T> = Proc<T, void>
# Using aliases
user_id: UserId = 123
email: EmailAddress = "alice@example.com"
Class Annotations
# Instance variables
class User
@name: String
@age: Integer
@email: String | nil
def initialize(name: String, age: Integer): void
@name = name
@age = age
@email = nil
end
def name: String
@name
end
def age: Integer
@age
end
end
# Class variables
class Counter
@@count: Integer = 0
def self.increment: void
@@count += 1
end
def self.count: Integer
@@count
end
end
# Generic class
class Container<T>
@value: T
def initialize(value: T): void
@value = value
end
def value: T
@value
end
end
Interface Definitions
# Basic interface
interface Printable
def to_s: String
end
# Interface with multiple methods
interface Comparable
def <=>(other: self): Integer
def ==(other: self): Boolean
end
# Generic interface
interface Collection<T>
def add(item: T): void
def remove(item: T): Boolean
def size: Integer
end
# Implementing interfaces
class User
implements Printable
@name: String
def initialize(name: String): void
@name = name
end
def to_s: String
"User: #{@name}"
end
end
Type Operators
| Operator | Name | Description | Example |
|---|---|---|---|
| | Union | Either/or types | String | Integer |
& | Intersection | Both types | Printable & Comparable |
? | Optional | Shorthand for | nil | String? |
<T> | Generic | Type parameter | Array<T> |
=> | Hash pair | Key-value type | Hash<String => Integer> |
# Union (OR)
value: String | Integer
# Intersection (AND)
class Person
implements Printable & Comparable
end
# Optional
name: String? # Same as String | nil
# Generics
items: Array<String>
pairs: Hash<String, Integer>
Blocks, Procs, and Lambdas
# Block parameter
def each_item<T>(items: Array<T>, &block: Proc<T, void>): void
items.each { |item| block.call(item) }
end
# Proc types
callback: Proc<String, void> = ->(msg: String): void { puts msg }
transformer: Proc<Integer, String> = ->(n: Integer): String { n.to_s }
# Lambda with types
double: Proc<Integer, Integer> = ->(n: Integer): Integer { n * 2 }
# Block with multiple parameters
def map<T, U>(items: Array<T>, &block: Proc<T, Integer, U>): Array<U>
items.map.with_index { |item, index| block.call(item, index) }
end
Type Narrowing
# Type checking with is_a?
def process(value: String | Integer): String
if value.is_a?(String)
value.upcase # T-Ruby knows value is String
else
value.to_s # T-Ruby knows value is Integer
end
end
# Nil checking
def get_length(text: String | nil): Integer
if text.nil?
0
else
text.length # T-Ruby knows text is String
end
end
# Multiple checks
def describe(value: String | Integer | Boolean): String
if value.is_a?(String)
"String: #{value}"
elsif value.is_a?(Integer)
"Number: #{value}"
else
"Boolean: #{value}"
end
end
Literal Types
# String literals
type Status = "pending" | "active" | "completed"
status: Status = "active"
# Number literals
type Port = 80 | 443 | 8080
port: Port = 443
# Symbol literals
type Role = :admin | :editor | :viewer
role: Role = :admin
# Boolean literals
type Yes = true
type No = false
Advanced Types
# Intersection types
type Serializable = Printable & Comparable
obj: Serializable # Must implement both interfaces
# Conditional types (planned)
type NonNullable<T> = T extends nil ? never : T
# Mapped types (planned)
type Readonly<T> = { readonly [K in keyof T]: T[K] }
# Utility types
type Partial<T> # All properties optional
type Required<T> # All properties required
type Pick<T, K> # Select properties
type Omit<T, K> # Remove properties
Type Assertions
# Type casting (use with caution)
value = get_value() as String
number = parse("42") as Integer
# Safe type conversion
def to_integer(value: String | Integer): Integer
if value.is_a?(Integer)
value
else
value.to_i
end
end
Module Type Annotations
module Formatter
# Module method with types
def self.format(value: String, width: Integer): String
value.ljust(width)
end
# Module constants with types
DEFAULT_WIDTH: Integer = 80
DEFAULT_CHAR: String = " "
end
# Mixin module
module Timestamped
@created_at: Integer
@updated_at: Integer
def timestamp: Integer
@created_at
end
end
Common Patterns
Optional Parameters with Defaults
def create_user(
name: String,
email: String,
age: Integer = 18,
active: Boolean = true
): User
User.new(name, email, age, active)
end
Result Type Pattern
type Result<T, E> = { success: Boolean, value: T | nil, error: E | nil }
def divide(a: Float, b: Float): Result<Float, String>
if b == 0
{ success: false, value: nil, error: "Division by zero" }
else
{ success: true, value: a / b, error: nil }
end
end
Builder Pattern
class QueryBuilder
@conditions: Array<String>
def initialize: void
@conditions = []
end
def where(condition: String): self
@conditions << condition
self
end
def build: String
@conditions.join(" AND ")
end
end
Type Guards
def is_string(value: Any): value is String
value.is_a?(String)
end
def is_user(value: Any): value is User
value.is_a?(User)
end
# Usage
value = get_value()
if is_string(value)
puts value.upcase # value is String here
end
Quick Tips
- Use type inference - Don't annotate everything, let T-Ruby infer simple types
- Prefer union types over Any -
String | Integeris better thanAny - Use type aliases - Make complex types readable with aliases
- Check types before use - Use
is_a?andnil?for union types - Leverage generics - Write reusable, type-safe code
- Start gradually - You don't need to type everything at once
- Use
voidfor side effects - Methods that don't return meaningful values - Avoid over-typing - If the type is obvious, let T-Ruby infer it
Common Type Errors
# ❌ Wrong: Assigning wrong type
name: String = 123 # Error: Integer is not String
# ✅ Correct: Use union type
id: String | Integer = 123
# ❌ Wrong: Accessing property without type check
def get_length(value: String | nil): Integer
value.length # Error: value might be nil
end
# ✅ Correct: Check for nil first
def get_length(value: String | nil): Integer
if value.nil?
0
else
value.length
end
end
# ❌ Wrong: Generic without type parameter
box = Box.new("hello") # Error if type can't be inferred
# ✅ Correct: Specify type parameter
box = Box<String>.new("hello")
File Extensions and Compilation
# T-Ruby source files
hello.trb
# Compile to Ruby
trc hello.trb
# Generates: hello.rb
# Generate RBS types
trc --rbs hello.trb
# Generates: hello.rbs
# Watch mode
trc --watch *.trb
# Type check only (no output)
trc --check hello.trb
Further Reading
- Built-in Types - Complete list of built-in types
- Type Operators - Detailed operator reference
- Standard Library Types - Ruby stdlib type definitions
- Type Aliases - Advanced aliasing techniques
- Generics - Generic programming guide