Type system

XS uses gradual typing. Code runs fine without annotations. Add them where you want enforcement; the checker activates only on annotated code.

Gradual typing

Unannotated code is never flagged. The type checker infers types where it can and silently passes through everything it cannot determine statically.

scratch.xs

Add an annotation and the checker enforces that specific location:

let x: int = "hello"
-- error[T0001]: type mismatch: expected 'int', got 'str'
--   hint: use int() or float() to convert a string to a number

Type annotations

Annotations go after a colon on bindings, after parameter names, and after -> for return types.

scratch.xs

Primitive types

int / i64      -- 64-bit signed integer (default)
i8, i16, i32   -- smaller signed integers
u8, u16, u32, u64  -- unsigned integers
float / f64    -- 64-bit float (default)
f32            -- 32-bit float
str / string   -- string
bool           -- boolean
char           -- character
byte           -- alias for u8
re             -- regex
any / dyn      -- any type (disables checking)
void / unit    -- no value
never          -- function that never returns

Use is for runtime type checks and as for casts:

scratch.xs

Composite types

scratch.xs

Checking modes

xs script.xs              -- normal: check annotated code, then run
xs --check script.xs      -- check only, don't execute
xs --strict script.xs     -- require annotations on everything
xs --lenient script.xs    -- downgrade type errors to warnings

In strict mode, every binding, parameter, and return type must be annotated:

-- xs --strict:
let x = 42
-- error[S0010]: missing type annotation for 'x' in strict mode

-- fix:
let x: int = 42

Type aliases

scratch.xs

Generics

Functions, structs, and enums can declare type parameters. Parameters can have variance markers and trait bounds.

scratch.xs
-- with trait bound
fn display<T: Describe>(item: T) -> str {
  return item.describe()
}

-- covariant (+T) and contravariant (-T) variance
struct Box<+T>  { inner }
struct Sink<-T> { accept }