Type: Package
Title: Runtime Type Checking
Version: 0.1.0
Description: Provides a lightweight runtime type system for 'R' that enables developers to declare and enforce variable types during execution. Inspired by 'TypeScript', the package introduces intuitive syntax for annotating variables and validating data structures, helping catch type-related errors early and making 'R' code more robust and easier to maintain.
License: MIT + file LICENSE
Encoding: UTF-8
URL: https://github.com/feddelegrand7/sicher
BugReports: https://github.com/feddelegrand7/sicher/issues
RoxygenNote: 7.3.2
Imports: glue (≥ 1.8.0)
Suggests: testthat
NeedsCompilation: no
Packaged: 2026-03-26 16:55:40 UTC; mohamedelfodilihaddaden
Author: Mohamed El Fodil Ihaddaden [aut, cre]
Maintainer: Mohamed El Fodil Ihaddaden <ihaddaden.fodeil@gmail.com>
Repository: CRAN
Date/Publication: 2026-03-31 10:00:02 UTC

Type-checked assignment operator

Description

Completes the typed assignment started with '%:%'.

Usage

typed_annotation %<-% value

Arguments

typed_annotation

Result of '%:%'.

value

Value to assign.

Value

Invisibly returns the assigned value.

Examples

x %:% Integer %<-% 5L
y %:% Double %<-% 3.14
name %:% String %<-% "Bob"
flag %:% Bool %<-% TRUE


Type annotation operator

Description

Creates a typed variable annotation used together with '%<-%'.

Usage

name %:% type

Arguments

name

Variable name (unevaluated).

type

Type specification (e.g., Integer, String, Double).

Value

A typed annotation object.

Examples

x %:% Integer %<-% 5L
name %:% String %<-% "Alice"
id %:% (Integer | String) %<-% 42L


Built-in Any Type

Description

A type that accepts any value.

Usage

Any

Format

An object of class sicher_type of length 2.


Built-in Boolean Type

Description

A type that checks for logical vectors.

Usage

Bool

Format

An object of class sicher_type of length 2.


Built-in DataFrame Type

Description

A type that checks for data.frame objects.

Usage

DataFrame

Format

An object of class sicher_type of length 2.


Built-in Double Type

Description

A type that checks for double-precision numeric vectors.

Usage

Double

Format

An object of class sicher_type of length 2.


Enum Type Factory

Description

Creates an enumeration type using regular function call syntax. The resulting type only accepts atomic vectors whose elements all belong to the declared set of allowed values.

Usage

Enum(...)

Arguments

...

Allowed scalar values or a single atomic vector of allowed values.

Value

A new sicher_type that checks all values belong to the enum.

Examples

status %:% Enum(1, 2, 3) %<-% 2
colors %:% Enum("red", "green", "blue") %<-% c("red", "blue")
try(colors <- c("yellow", "red"))

Built-in Function Type

Description

A type that checks for function objects.

Usage

Function

Format

An object of class sicher_type of length 2.


Built-in Integer Type

Description

A type that checks for integer vectors.

Usage

Integer

Format

An object of class sicher_type of length 2.


Built-in List Type

Description

A type that checks for list objects.

Usage

List

Format

An object of class sicher_type of length 2.


Create a homogeneous list type

Description

Produces a type that validates a list whose every element satisfies the provided element type. This is useful when you expect a list of similar records (e.g. parsed JSON array). You can further constrain the length with the size operator: 'ListOf(User)[10]'.

Usage

ListOf(element_type)

Arguments

element_type

A sicher_type or sicher_union describing each element.

Value

A sicher_type that checks the value is a list and that all elements conform to 'element_type'.

Examples

# Define an inner record type
Record <- create_list_type(list(id = Numeric, name = String))

# Now require a list of records
Records <- ListOf(Record)
records %:% Records %<-% list(
  list(id = 1, name = "a"),
  list(id = 2, name = "b")
)

# fixed-size list of ten records
TenRecs <- Records[10]
# will throw if length != 10


Built-in Null Type

Description

A type that checks for NULL values.

Usage

Null

Format

An object of class sicher_type of length 2.


Built-in Numeric Type

Description

A type that checks for numeric vectors (integer or double).

Usage

Numeric

Format

An object of class sicher_type of length 2.


Create an optional (nullable) type variant

Description

Creates a type that accepts NULL values in addition to the base type.

Usage

Optional(type)

Arguments

type

A sicher_type object

Value

A union type that includes Null

Examples

middle_name %:% Optional(String) %<-% NULL
middle_name <- "Marie"  # Also OK


Create a readonly type variant

Description

Creates a type that prevents reassignment after initial value is set.

Usage

Readonly(type)

Arguments

type

A sicher_type object

Value

A readonly type modifier

Examples

PI %:% Readonly(Double) %<-% 3.14159
try(PI <- 3.0)  # Error: cannot reassign readonly


Create a scalar (length-1) type variant

Description

Creates a type that only accepts single values (vectors of length 1).

Usage

Scalar(type)

Arguments

type

A sicher_type object

Value

A new sicher_type that checks for length 1

Examples

age %:% Scalar(Integer) %<-% 30L
try(age <- c(30L, 40L))  # Error: not scalar


Built-in String Type

Description

A type that checks for character vectors.

Usage

String

Format

An object of class sicher_type of length 2.


Vector Size Operator for sicher_type

Description

Creates a type that checks for a specific vector length.

Usage

## S3 method for class 'sicher_type'
type[size]

Arguments

type

A sicher_type object

size

The required length (non-negative integer)

Value

A new sicher_type that checks for the specified length

Examples

vec %:% Numeric[3] %<-% c(1, 2, 3)
try(vec <- c(1, 2)) # Error: wrong length
try(vec <- c("a", "b", "c"))  # Error: wrong type


Type Checking Function

Description

Validates that a value conforms to a specified type. This is the core validation function used internally by the type system, but can also be called directly for manual type checking.

Usage

check_type(value, type, context = NULL)

Arguments

value

The value to check

type

A sicher_type, sicher_union, or sicher_readonly object

context

Optional character string describing where the check is occurring (used in error messages)

Details

This function:

Value

Returns 'TRUE' invisibly if the value matches the type, otherwise throws an error with a descriptive message.

See Also

create_type for creating custom types

Examples

# Direct type checking
check_type(5L, Integer)  # Returns TRUE
try(check_type("hello", Integer))  # Throws error

# With context for better error messages
try(check_type(5L, String, context = "user_name"))

# With union types
check_type(5L, Integer | String)  # Returns TRUE
try(check_type(5.5, Integer | String))  # Throws error


Create a Data Frame Type with Column Specification

Description

Builds a type that validates a data frame's column names and their types. Each column is treated as a vector and checked against the provided sicher_type (or union) specification. Optional columns may be declared with 'Optional()'.

Usage

create_dataframe_type(col_spec)

Arguments

col_spec

A named list where names are column names and values are sicher_type or sicher_union objects describing the expected column type.

Value

A sicher_type representing the data frame schema.

Examples

PersonDF <- create_dataframe_type(list(
  name = String,
  age = Numeric,
  height = Optional(Numeric)
))

df %:% PersonDF %<-% data.frame(
  name = c("Alice", "Bob"),
  age = c(25, 30)
)


Create a List Type with Specific Structure

Description

Creates a type that checks for lists with specific named elements and their types. Similar to object types in TypeScript/JavaScript.

Usage

create_list_type(type_spec)

Arguments

type_spec

A named list where names are field names and values are sicher_type objects

Value

A sicher_type that validates list structure

Examples

# Define a User type
User <- create_list_type(list(
  name = String,
  age = Numeric,
  preferences = create_list_type(list(
    color = String,
    movie = String
  ))
))

# Use it
user %:% User %<-% list(
  name = "Alice",
  age = 25,
  preferences = list(color = "red", movie = "batman")
)


Create a Custom Type

Description

Creates a new type object for use in the type checking system. A type consists of a name (for error messages) and a checker function (for validation).

Usage

create_type(name, checker)

Arguments

name

A single character string representing the type name. This name will be displayed in error messages when type checking fails.

checker

A function that takes a single argument and returns 'TRUE' if the value matches the type, 'FALSE' otherwise. The checker function should be a predicate (e.g., 'is.numeric', 'is.character').

Details

This is the fundamental building block of the type system. Built-in types like 'Integer', 'Double', and 'String' are all created using this function.

The checker function should:

Value

An object of class '"sicher_type"' containing:

name

The type name as a character string

check

The checker function

See Also

check_type for type validation, Scalar for creating scalar type variants, Readonly for creating readonly type variants

Examples

# Create a custom positive number
Positive <- create_type("positive", function(x) {
  is.numeric(x) && all(x > 0)
})

# Use it in type annotations
age %:% Positive %<-% 25
try(age <- -5)  # Error: Type error

# Create a custom email type
Email <- create_type("email", function(x) {
  is.character(x) &&
    length(x) == 1 &&
    grepl("^[^@]+@[^@]+\\.[^@]+$", x)
})

user_email %:% Email %<-% "user@example.com"

# Create a type for even integers
EvenInt <- create_type("even_int", function(x) {
  is.integer(x) && all(x %% 2 == 0)
})

value %:% EvenInt %<-% 4L
try(value <- 5L)  # Error: Type error

# Create a type that checks data frame structure
PersonDF <- create_type("person_df", function(x) {
  is.data.frame(x) &&
    all(c("name", "age") %in% names(x)) &&
    is.character(x$name) &&
    is.numeric(x$age)
})


Infer a Type from an R Object

Description

Infers the most appropriate sicher type constructor for a given R object. By default, inference focuses on the underlying type and does not lock in the observed length of vectors. Set 'strict = TRUE' to also infer scalar and fixed-size vector constraints from the example value.

Usage

infer_type(obj, strict = FALSE)

Arguments

obj

Any R object (primitive, vector, list, data.frame, function, etc.)

strict

Logical scalar. When 'FALSE' (default), infer only the base type shape, such as 'Numeric', 'String', 'ListOf(Integer)', or a 'create_dataframe_type()' schema without fixed lengths. When 'TRUE', also infer 'Scalar()' and '[n]' size constraints from the observed object.

Value

A sicher_type object (e.g., Numeric, String, create_list_type(...), ListOf(...), etc.)

Examples

infer_type(42L)                # Integer
infer_type(3.14)               # Double
infer_type(c(1, 2, 3))         # Double or Numeric, no length constraint
infer_type("abc")              # String
infer_type(c("a", "b"))        # String
infer_type(TRUE)               # Bool
infer_type(NULL)               # Null
infer_type(function(x) x + 1)  # Function
infer_type(list(a = 1, b = "x"))   # create_list_type(list(a = Double, b = String))
infer_type(list(1, 2, 3))           # ListOf(Double)
infer_type(data.frame(x = 1:3))     # create_dataframe_type(list(x = Integer))
infer_type(list(a = NULL, b = 1))   # create_list_type(list(a = Optional(Any), b = Double))

# Strict mode keeps observed length constraints
infer_type(42L, strict = TRUE)          # Scalar(Integer)
infer_type(c("a", "b"), strict = TRUE)  # String[2]

Print method for sicher_type

Description

Print method for sicher_type

Usage

## S3 method for class 'sicher_type'
print(x, ...)

Arguments

x

A sicher_type object

...

Additional arguments (ignored)

Value

Invisibly returns the input object


Print method for sicher_typed_annotation

Description

Print method for sicher_typed_annotation

Usage

## S3 method for class 'sicher_typed_annotation'
print(x, ...)

Arguments

x

A sicher_typed_annotation object

...

Additional arguments (ignored)

Value

Invisibly returns the input object


Print method for sicher_typed_function

Description

Print method for sicher_typed_function

Usage

## S3 method for class 'sicher_typed_function'
print(x, ...)

Arguments

x

A sicher_typed_function object

...

Additional arguments (ignored)

Value

Invisibly returns the input object


Print method for sicher_union

Description

Print method for sicher_union

Usage

## S3 method for class 'sicher_union'
print(x, ...)

Arguments

x

A sicher_union object

...

Additional arguments (ignored)

Value

Invisibly returns the input object


Create a type-checked function

Description

Wraps a function with runtime type checking for its parameters and, optionally, its return value. This is the function counterpart to the typed variable operators ('%:%' / '%<-%'), providing a syntax analogous to typed function signatures:

  add <- typed_function(
    function(x, y) x + y,
    params  = list(x = Numeric, y = Numeric),
    .return = Numeric
  )

Usage

typed_function(fn, params = list(), .return = NULL)

Arguments

fn

The function to wrap. Its formals are preserved in the wrapper so callers use the exact same signature.

params

A named list mapping parameter names to their types (e.g. list(x = Numeric, y = String)). Only listed parameters are type-checked on each call; unlisted parameters pass through unchecked. Defaults to an empty list (no parameter checking).

.return

Optional return type. When NULL (the default), the return value is not checked. Accepts any sicher_type or sicher_union.

Value

A function with the same formals as fn and S3 class "sicher_typed_function" that:

Examples

# Basic typed function
add <- typed_function(
  function(x, y) x + y,
  params  = list(x = Numeric, y = Numeric),
  .return = Numeric
)
add(1, 2)     # Returns 3
try(add("a", 2))   # Error: Type error in 'x': Expected numeric, got string

# Optional parameter
greet <- typed_function(
  function(name, title = NULL) {
    if (is.null(title)) paste("Hello,", name)
    else paste("Hello,", title, name)
  },
  params = list(name = String, title = Optional(String))
)
greet("Alice")                   # "Hello, Alice"
greet("Alice", title = "Dr.")    # "Hello, Dr. Alice"
try(greet("Alice", title = 42))  # Error: Type error in 'title'

# Union type in params
describe <- typed_function(
  function(id) paste("ID:", id),
  params  = list(id = String | Numeric),
  .return = String
)
describe("abc")  # "ID: abc"
describe(123)    # "ID: 123"
try(describe(TRUE)) # Error: Type error in 'id'


Union Type Operator

Description

S3 methods for the '|' operator to create union types.

Usage

## S3 method for class 'sicher_type'
type1 | type2

## S3 method for class 'sicher_union'
type1 | type2

Arguments

type1

First type (sicher_type or sicher_union object)

type2

Second type (sicher_type or sicher_union object)

Value

A union type (sicher_union object)