/ foundation

Ridiculous Type Kit

The shared template-literal machinery every ridiculous component is built on โ€” character and number primitives, CSS dimension validators, and paren-aware parser combinators. Pure types, zero runtime.

Installed automatically as a registryDependency of every component โ€” you rarely add it by hand. Import from @/lib/ridiculous-type-kit when you want to compose your own ridiculously-typed CSS validators.
/ exports

What's in the box

All pure types โ€” no runtime cost. Combine them into your own template-literal CSS validators.

Characters & logic

String walking, trimming, and the boolean combinators every validator is built from.

DigitHexDigitWSTrimLeftTrimRightTrimAllCharsNonEmptyAllCharsAndOrNotKeepIfLength

Numbers & ranges

Range-checked numeric validators โ€” the type-level math that rejects out-of-gamut tokens.

IntRangeIsNonNegativeNumberIsSignedDecimalIsNumberIsPositiveIntIsByteIsNumber0To1IsNumber0To100IsNumber0To360IsNumber0To400IsPercent0To100

CSS dimensions

Per-unit predicates plus DimensionOf โ€” classify any value literal as length, angle, time, โ€ฆ

IsLengthIsAngleIsTimeIsResolutionIsPercentageIsFlexDimensionDimensionOf

Parser combinators

Paren-aware splitting and function parsing โ€” the backbone of every list and function grammar.

StartsWithEndsWithSplitByCommaSplitBySpaceParseFunction
/ api

API reference

Every export with its signature and a worked input โ†’ output. Results are compile-time types โ€” exactly what TypeScript resolves the expression to, mirrored from the type-test suite.

ยง Characters & logic

Digit= "0" | "1" | โ€ฆ | "9"

Decimal-digit char union. The allow-list you hand to AllChars.

AllChars<"42", Digit> โ†’ true
HexDigit= Digit | "a"โ€ฆ"f" | "A"โ€ฆ"F"

Hex-digit char union (both cases).

AllChars<"FF", HexDigit> โ†’ true
WS= " " | "\n" | "\t"

The whitespace chars Trim consumes.

TrimLeft<S>

Drop leading whitespace.

TrimLeft<" x"> โ†’ "x"
TrimRight<S>

Drop trailing whitespace.

TrimRight<"x "> โ†’ "x"
Trim<S>

Drop whitespace on both ends. Used everywhere before a predicate runs.

Trim<" hi "> โ†’ "hi"Trim<"none"> โ†’ "none"
AllChars<S, Allowed>

Is every char of S a member of the Allowed union? The empty string is true.

AllChars<"123", Digit> โ†’ trueAllChars<"12a", Digit> โ†’ false
NonEmptyAllChars<S, Allowed>

AllChars, but the empty string is false โ€” the variant most predicates want.

NonEmptyAllChars<"12", Digit> โ†’ trueNonEmptyAllChars<"", Digit> โ†’ false
And<A, B>

Boolean conjunction over true | false.

And<true, true> โ†’ trueAnd<true, false> โ†’ false
Or<A, B>

Boolean disjunction.

Or<false, true> โ†’ trueOr<false, false> โ†’ false
Not<A>

Boolean negation.

Not<true> โ†’ false
KeepIf<B, S>

The collapse step: keep S when B is true, else never. Turns a predicate into an S | never validator.

KeepIf<true, "x"> โ†’ "x"KeepIf<false, "x"> โ†’ never
Length<S>

Count the characters in S as a number literal.

Length<"abc"> โ†’ 3Length<""> โ†’ 0

ยง Numbers & ranges

IntRange<From, To>

Half-open numeric-literal range โ€” From inclusive, To exclusive. Powers the bounded validators below.

IntRange<0, 3> โ†’ 0 | 1 | 2
IsNonNegativeNumber<S>

Digits with an optional fractional part. No sign.

IsNonNegativeNumber<"3.14"> โ†’ trueIsNonNegativeNumber<"-1"> โ†’ false
IsSignedDecimal<S>

A non-negative number with an optional leading minus.

IsSignedDecimal<"-0.05"> โ†’ trueIsSignedDecimal<"+2"> โ†’ false
IsNumber<S>

A decimal with an optional leading + or -. The broadest numeric shape.

IsNumber<"+2"> โ†’ trueIsNumber<"2px"> โ†’ false
IsPositiveInt<S>

An integer โ‰ฅ 1 (rejects 0 and the empty string).

IsPositiveInt<"3"> โ†’ trueIsPositiveInt<"0"> โ†’ false
IsByte<S>

Integer 0โ€“255 โ€” the RGB channel range.

IsByte<"255"> โ†’ trueIsByte<"256"> โ†’ falseIsByte<"-1"> โ†’ false
IsNumber0To1<S>

Number in 0โ€“1 inclusive โ€” the alpha / opacity range.

IsNumber0To1<"0.5"> โ†’ trueIsNumber0To1<"1.1"> โ†’ false
IsNumber0To100<S>

Number in 0โ€“100 inclusive.

IsNumber0To100<"100"> โ†’ trueIsNumber0To100<"101"> โ†’ false
IsNumber0To360<S>

Number in 0โ€“360 inclusive โ€” the hue-degree range.

IsNumber0To360<"360"> โ†’ true
IsNumber0To400<S>

Number in 0โ€“400 inclusive.

IsNumber0To400<"400"> โ†’ trueIsNumber0To400<"401"> โ†’ false
IsPercent0To100<S>

An N% literal whose N lands in 0โ€“100.

IsPercent0To100<"50%"> โ†’ trueIsPercent0To100<"150%"> โ†’ false

ยง CSS dimensions

IsLength<S>

A number plus a CSS length unit โ€” px, rem, em, vh, cqmin, and the rest.

IsLength<"10px"> โ†’ trueIsLength<"1.5rem"> โ†’ trueIsLength<"45deg"> โ†’ falseIsLength<"10"> โ†’ false
IsAngle<S>

A number plus deg / grad / rad / turn.

IsAngle<"45deg"> โ†’ trueIsAngle<"0.25turn"> โ†’ true
IsTime<S>

A number plus s / ms.

IsTime<"200ms"> โ†’ trueIsTime<"1.5s"> โ†’ true
IsResolution<S>

A number plus dpi / dpcm / dppx / x.

IsResolution<"2dppx"> โ†’ trueIsResolution<"96dpi"> โ†’ true
IsPercentage<S>

Any N% literal (unbounded โ€” pair with IsPercent0To100 to clamp the range).

IsPercentage<"50%"> โ†’ true
IsFlex<S>

A non-negative Nfr grid flex value.

IsFlex<"1fr"> โ†’ trueIsFlex<"-1fr"> โ†’ false
Dimension= "length" | "angle" | "time" | "percent" | "number" | "flex" | "resolution"

The tag union DimensionOf resolves to.

DimensionOf<S>

Classify a value literal as its Dimension tag (trims first); never for nonsense.

DimensionOf<"10px"> โ†’ "length"DimensionOf<"45deg"> โ†’ "angle"DimensionOf<"3"> โ†’ "number"DimensionOf<"nonsense"> โ†’ never

ยง Parser combinators

StartsWith<S, P>

Does S begin with the prefix P?

StartsWith<"calc(1px)", "calc("> โ†’ trueStartsWith<"min(1px)", "calc("> โ†’ false
EndsWith<S, P>

Does S end with the suffix P?

EndsWith<"10px", "px"> โ†’ trueEndsWith<"10em", "px"> โ†’ false
SplitByComma<S>

Split on top-level commas, ignoring those nested in parens or brackets. Trims each token; keeps empties.

SplitByComma<"a, b(c, d), e"> โ†’ ["a", "b(c, d)", "e"]
SplitBySpace<S>

Split on top-level whitespace, paren-aware. Collapses runs (drops empties).

SplitBySpace<"translateX(1px) rotate(45deg)"> โ†’ ["translateX(1px)", "rotate(45deg)"]SplitBySpace<"rgb(255 0 0)"> โ†’ ["rgb(255 0 0)"]
ParseFunction<S>

Split the outer call into its name and raw args; never when S is not a call.

ParseFunction<"minmax(0, 1fr)"> โ†’ { name: "minmax"; args: "0, 1fr" }ParseFunction<"not-a-call"> โ†’ never
/ pattern

The call-site helper idiom

Predicates gate a value; KeepIf collapses the result; a one-line identity function carries the constraint to the call site. Three recipes from real components.

Validation lives entirely in the type system. The runtime helper is a one-line identity function that simply carries the constraint โ€” there is no runtime cost and nothing to execute. It cannot be factored into a shared helper because TypeScript has no higher-kinded types, so each component copies this one line, swapping in its own Literal validator:
const x = <S extends string>(v: S & XLiteral<S>): S => v
/ strict-length

A length-only helper

Compose IsLength with KeepIf to accept any valid CSS length and reject everything else at compile time.

import type { IsLength, KeepIf } from "@/lib/ridiculous-type-kit"

type Length<S extends string> = KeepIf<IsLength<S>, S>

export const len = <S extends string>(v: S & Length<S>): S => v

len("16px")   // โœ“
len("1.5rem") // โœ“
// @ts-expect-error โ€” "16deg" is an angle, not a length
len("16deg")
/ bounded-alpha

A 0โ€“1 alpha helper

Swap in a different predicate and the same idiom now clamps a number to the 0โ€“1 opacity range.

import type { IsNumber0To1, KeepIf } from "@/lib/ridiculous-type-kit"

type Alpha<S extends string> = KeepIf<IsNumber0To1<S>, S>

export const alpha = <S extends string>(v: S & Alpha<S>): S => v

alpha("0.5") // โœ“
// @ts-expect-error โ€” 1.1 is outside the 0โ€“1 range
alpha("1.1")
/ classify-parse

Classify & parse

The non-boolean exports: tag a token by its CSS dimension, or pull a function call apart into name + comma-separated args.

import type {
  DimensionOf,
  ParseFunction,
  SplitByComma,
} from "@/lib/ridiculous-type-kit"

type T1 = DimensionOf<"200ms">       // "time"
type T2 = DimensionOf<"1fr">         // "flex"

type Fn = ParseFunction<"minmax(0, 1fr)">
//   ^? { name: "minmax"; args: "0, 1fr" }
type Args = SplitByComma<Fn["args"]> // ["0", "1fr"]
/ install

Drop it in

Usually pulled in transitively, but you can install the kit on its own.

$ pnpm dlx shadcn@latest add https://turtiesocks.github.io/ridiculous/r/ridiculous-type-kit.json