Skip to main content

Type-safe R for long-lived software.

PackagesShiny applicationsData pipelinesAPIs

curl -fsSL https://we-data-ch.github.io/typr.github.io/install/install.sh | sh

One command, no admin rights, checksum verified. Other ways to install

TypR is R, with types.

TypR compiles to ordinary R and runs on its ecosystem as-is — the same packages, the same Shiny apps, the same tools you already use.

TypR
R
R at the core. TypR is the typed layer around it.
  1. TypR source filemain.ty
  2. TypR compilertypr build
  3. R source filemain.R
The compiler turns typed source into the R code you ship.

Zero lock-in. The generated main.R is plain, idiomatic R — no TypR runtime, no added dependency. Stop using TypR any time, and the code you shipped keeps running exactly as it did.

Your data model should not live in people’s heads.

R projects start as scripts. The ones that turn into packages, Shiny applications or data pipelines end up maintained for years — and by then, the shape of the data is what everyone needs to know. Define it once, and use it throughout your system.

TypRRun in playground →
type Order <- list {
  id: int,
  total: num
};

type Customer <- list {
  id: int,
  name: char,
  orders: [Order]
};
Customer
  • Packagetyped functions
  • Shinytyped reactives
  • APItyped responses
One definition, the same meaning everywhere it is used.

What R lets through, TypR stops.

Mistakes that R reports late, or never. Each one below is rejected by the compiler before the code runs.

Replace hand-written checks with a type.

R
set_alpha <- function(alpha) {
  stopifnot(
    is.numeric(alpha),
    length(alpha) == 1,
    alpha >= 0,
    alpha <= 1
  )
  alpha
}

set_alpha(1.5)
# Four lines of checks, and they only
# fire when this call finally runs.
TypRRun in playground →
let set_alpha <- fn(
  alpha: num & (>= 0.0) & (<= 1.0)
): num {
  alpha
};

set_alpha(1.5);

The range lives in the signature. A literal that breaks it is rejected at compile time; a value only known at run time gets one check, at the call.

typr check
  × Type error: No signature of function 'set_alpha' matches this call.
   ╭─[contracts.ty:7:2]
 6 │ 
 7 │ set_alpha(1.5);
   ·  ────┬────
   ·      ╰── Called with 1 argument(s): (1.5)
   ╰────
  help: 'set_alpha' exists but none of its signature(s) accepts these
        arguments:
            ((<= 1) & (>= 0) & num) -> num

See R become typed.

Here is that discipline applied to the R code you already write.

Build packages with explicit contracts.

R
summarise_sales <- function(sales, region) {
  # What is `sales`? A list? A data.frame?
  # What comes back? A number? A vector?
  # Only the body knows, and only at run time.
  sum(sales$amount[sales$region == region])
}
TypRRun in playground →
type Sale <- list { region: char, amount: num };

let summarise_sales <- fn(
  sales: [Sale],
  region: char
): num {
  (sales) |> filter(\(s) s$region == region)
          |> map(\(s) s$amount)
          |> sum()
};

A function signature becomes part of the documentation and the contract of your package.

One language. One toolchain.

The typr command provides the tools needed to build, explore and maintain TypR projects.

typr
Compilercheck, build
REPLexplore
Project managernew, run, test
LSPeditors
One binary. Every tool talks to the same compiler and the same types.

Build software that lasts.

Start building your next R package, application or data system with TypR. One command installs it.

curl -fsSL https://we-data-ch.github.io/typr.github.io/install/install.sh | sh

One command, no admin rights, checksum verified. Other ways to install