Skip to main content

Declaration Files (.d.infr)

Declaration files describe the types of existing R packages so Infr can check calls to them. They are analogous to TypeScript's .d.ts files.

Syntax

base.d.infr
#' @infr
paste <- function(...: character, sep: character = " ") -> character
nchar <- function(x: character) -> integer
sum <- function(...: numeric, na.rm: logical = FALSE) -> numeric
mean <- function(x: numeric, na.rm: logical = FALSE) -> numeric
c <- function<T>(...: T) -> T
length <- function(x: any) -> integer
is.null <- function(x: any) -> logical
is.numeric <- function(x: any) -> logical

Each declaration is a function signature without a body. The #' @infr comment marks the file as a declaration file.

Built-in declarations

Infr ships with declarations for common R packages:

PackageFileDescription
basebase.d.infrCore R functions (~350+ signatures)
statsstats.d.infrStatistical functions
dplyrdplyr.d.infrData manipulation
ggplot2ggplot2.d.infrPlotting
tidyrtidyr.d.infrData tidying
purrrpurrr.d.infrFunctional programming
readrreadr.d.infrData import
stringrstringr.d.infrString manipulation

Using additional declarations

Add external declaration files in infr.toml:

infr.toml
[declarations]
include = [
"types/my-package.d.infr"
]

Writing your own

Create a .d.infr file with function signatures for any R package:

httr.d.infr
#' @infr
GET <- function(url: character, ...: any) -> any
POST <- function(url: character, body: any, ...: any) -> any
content <- function(x: any, as: character = "text") -> any
status_code <- function(x: any) -> integer

Start with any types and refine as needed. Partial declarations are perfectly valid — undeclared functions are simply unchecked.

Function overloads

Declare multiple signatures for the same function to define overloads. Infr automatically merges them:

utils.d.infr
#' @infr
print <- function(x: numeric) -> character
print <- function(x: character) -> character
print <- function(x: logical) -> character

At call sites, Infr picks the first matching overload based on argument types. This is useful for R functions that behave differently depending on input types.

Generics in declarations

identity <- function<T>(x: T) -> T
c <- function<T>(...: T) -> T
map_vec <- function<T, U>(x: T, f: (T) -> U) -> U

See the Declarations Overview for details on the bundled declarations.