Type Annotations
Type annotations tell Infr what types you expect. They are optional — Infr infers types wherever possible — but annotations help with documentation and catch errors at function boundaries.
Variable annotations
Add a type after the variable name with ::
const x: numeric <- 5
let name: character <- "Alice"
const flag: logical <- TRUE
const items: list <- list(1, "a", TRUE)
Function signatures
Annotate parameters with : and return types with ->:
add <- function(x: numeric, y: numeric) -> numeric {
x + y
}
greet <- function(name: character, excited: logical = FALSE) -> character {
if (excited) {
paste0("Hello, ", name, "!")
} else {
paste("Hello", name)
}
}
When annotations are present, Infr checks:
- Arguments are called with correct types
- The return value matches the declared return type
- Default values match the parameter type
When annotations are absent, the function is unchecked (gradual typing).
Data frame types
Data frames get first-class typed support:
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$name # character
df$nonexistent # Error [infr]: Column `nonexistent` does not exist
Named list types
const person: list<{name: character, age: numeric}> <- list(name = "Alice", age = 30)
person$name # character
person$age # numeric
person$email # Error [infr]: Field `email` does not exist on list<{name, age}>
Nullable types
Use ? to indicate a type that can be NULL:
find_user <- function(id: integer) -> character? {
if (id > 100) NULL
else "Alice"
}
See the Types Reference for the complete type system.
Function types
const transformer: (numeric) -> numeric <- function(x: numeric) -> numeric { x * 2 }
apply_fn <- function(f: (numeric) -> numeric, x: numeric) -> numeric {
f(x)
}
Type aliases
Create named types to reduce repetition:
type Score = numeric
type Person = list<{name: character, age: numeric}>
add_scores <- function(a: Score, b: Score) -> Score { a + b }
const alice: Person <- list(name = "Alice", age = 30)
See the Types Reference for full details.
Literal types
Use exact values as types:
type Direction = "north" | "south" | "east" | "west"
type Dice = 1 | 2 | 3 | 4 | 5 | 6
See the Types Reference for full details.
Union types
const value: numeric | character <- if (flag) 42 else "hello"
if (is.numeric(value)) {
value + 1 # OK — narrowed to numeric
} else {
nchar(value) # OK — narrowed to character
}