Type System Reference
Complete reference for all types in Infr.
Primitive types
These map directly to R's atomic vector types:
| Infr type | R typeof | Examples |
|---|---|---|
numeric | double | 3.14, 1e10 |
integer | integer | 1L, 2L |
character | character | "hello" |
logical | logical | TRUE, FALSE |
complex | complex | 1+2i |
raw | raw | as.raw(0x1f) |
All of these are vectors. numeric means "a numeric vector" (possibly of length 1).
Compound types
Lists
const mixed: list <- list(1, "a", TRUE)
Named lists (record-like)
const person: list<{name: character, age: numeric}> <- list(name = "Alice", age = 30)
person$name # character
person$age # numeric
person$email # Error: Field `email` does not exist
Data frames
const df: data.frame<{
id: integer,
name: character,
score: numeric
}> <- data.frame(
id = 1:3L,
name = c("Alice", "Bob", "Charlie"),
score = c(95.5, 87.0, 92.3)
)
df$score # numeric
df$nonexistent # Error: Column `nonexistent` does not exist
Special types
| Type | Meaning |
|---|---|
any | Opts out of type checking. Escape hatch. |
NULL | The R NULL value. |
T? | Nullable: T or NULL. Shorthand for T | NULL. |
Type aliases
Define reusable type names with type:
type Score = numeric
type MaybeString = character?
type StringOrNum = character | numeric
type Person = list<{name: character, age: numeric}>
Use them anywhere a type annotation is expected:
add_scores <- function(a: Score, b: Score) -> Score { a + b }
const alice: Person <- list(name = "Alice", age = 30)
Type aliases are erased during transpilation — they produce no R output.
Literal types
String, numeric, and integer literals can be used as types, representing exact values:
type Greeting = "hello" | "goodbye"
type Dice = 1 | 2 | 3 | 4 | 5 | 6
type Status = "active" | "inactive" | numeric
Literal types are subtypes of their base types — "hello" is assignable to character, but character is not assignable to "hello".
Union types
const value: numeric | character <- if (flag) 42 else "hello"
Function types
const transformer: (numeric) -> numeric <- function(x: numeric) -> numeric { x * 2 }
Overloaded functions
Functions can have multiple signatures via .d.infr declaration files. When the same function name is declared multiple times, the signatures are merged into an overloaded type:
#' @infr
as.character <- function(x: numeric) -> character
as.character <- function(x: logical) -> character
as.character <- function(x: complex) -> character
At call sites, Infr resolves the best matching overload based on argument types. If no overload matches, all available signatures are shown in the error message.
Generics
Simple type parameters for functions:
identity <- function<T>(x: T) -> T { x }
c <- function<T>(...: T) -> T
Type narrowing
Infr narrows types inside conditional branches based on type-checking functions:
const x: numeric | character <- get_value()
if (is.numeric(x)) {
x + 1 # x is numeric here
}
const y: numeric? <- maybe_get()
if (!is.null(y)) {
y * 2 # y is numeric here
}
if (inherits(obj, "data.frame")) {
nrow(obj) # obj is data.frame here
}
Supported narrowing functions:
is.numeric(),is.character(),is.logical(),is.integer()is.null()/!is.null()inherits()