@statili · regression & distributions for TypeScript

Two packages: one fits the model, one explains the fit.

@statili/stats

Eight regression and smoothing models, in modern type-safe TypeScript. Every fit reports its standard error, p‑value and confidence interval — or a typed reason it could not fit at all. 557 tests, validated against closed-form solutions and published statistical tables.

@statili/forge

A deterministic fact generator. It turns a result into structured claims — a kind, a narrowed claim, a level, and the provenance to audit it. Never prose, so one fact becomes an aria-label, a full text alternative, or a row feeding an enrichment pipeline.

Most regression libraries return a plausible answer even when the data can’t support one. statili refuses.

Every result is a discriminated union — a fitted model, or a typed reason it couldn’t fit one. Standard errors, p‑values and confidence intervals ship with every estimate, not as an afterthought.

TypeScript
import { linear } from '@statili/stats'

const result = linear({ precision: 2 }, [[1, 12], [2, 19], [3, 29], [4, 37]])

if (!result.ok) return console.error(result.errorType, result.message)

result.slope           // 8.5
result.pValueM         // 0.0021
result.slopeInterval   // [6.83, 10.17]
result.interval(6)     // { fit: 54, lower: 47.88, upper: 60.12 }

Results are marked, not just returned:

finding caveat failure

It refuses to guess

Three points that share an x-coordinate. There is no line to fit. Here is what each library does with that.

[email protected]

slope: 0, r²: 0 — no warning

@statili/[email protected]

errorType: DegenerateInput
“all x-values are identical — no line is defined”

regression
import regression from 'regression'

regression.linear([[3,10],[3,15],[3,22]])
// { equation: [0, 15.67], r2: 0,
//   points: [[3,15.67],[3,15.67],[3,15.67]] }
@statili/stats
import { linear } from '@statili/stats'

linear({}, [[3,10],[3,15],[3,22]])
// { ok: false, errorType: 'DegenerateInput',
//   message: 'all x-values are identical —
//              no line is defined' }

Every failure is typed

A discriminated union of five error types, not a thrown exception and not a silent NaN.

InsufficientData

Fewer points than the model needs to be identified.

DegenerateInput

The data has no variation along an axis the model requires.

InvalidInput

Non-finite values, mismatched lengths, or out-of-range options.

MathError

A computation that is undefined for these inputs, such as a singular matrix.

NumericalStability

A result the solver does not trust to the requested precision.

It states its uncertainty

Not just a slope. Standard error, p‑value, degrees of freedom, and a band you can draw — on the left from @statili/stats, and on the right the same numbers after @statili/forge has turned them into facts. The sentences are generated from the fit, so they cannot drift from it.

week 6 fit 54.0 [47.88, 60.12]

slope 8.5se 0.62p 0.0021df 2

rendered by @statili/forge

aria-label (short)

Signups rising with week — slope 7.85, p < 0.001.

full text alternative

Each additional unit of week is associated with an increase of 7.85 users in signups. The slope of 7.85 is statistically significant (p = 8.7e-9, 6 degrees of freedom).

insight

Unlikely to be due to chance (p = 0.0021).

caveat

n = 4 — treat the interval as indicative, not final.

Six packages

Use the whole stack, or take one layer at a time.

557

tests, including validation against closed-form solutions and published statistical tables

2017

regression has not changed since

2020

highcharts-regression has not changed since, and has no test suite