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.
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.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.
DigitHexDigitWSTrimLeftTrimRightTrimAllCharsNonEmptyAllCharsAndOrNotKeepIfLengthNumbers & ranges
Range-checked numeric validators โ the type-level math that rejects out-of-gamut tokens.
IntRangeIsNonNegativeNumberIsSignedDecimalIsNumberIsPositiveIntIsByteIsNumber0To1IsNumber0To100IsNumber0To360IsNumber0To400IsPercent0To100CSS dimensions
Per-unit predicates plus DimensionOf โ classify any value literal as length, angle, time, โฆ
IsLengthIsAngleIsTimeIsResolutionIsPercentageIsFlexDimensionDimensionOfParser combinators
Paren-aware splitting and function parsing โ the backbone of every list and function grammar.
StartsWithEndsWithSplitByCommaSplitBySpaceParseFunctionAPI 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.
HexDigit= Digit | "a"โฆ"f" | "A"โฆ"F"Hex-digit char union (both cases).
WS= " " | "\n" | "\t"The whitespace chars Trim consumes.
TrimLeft<S>Drop leading whitespace.
TrimRight<S>Drop trailing whitespace.
Trim<S>Drop whitespace on both ends. Used everywhere before a predicate runs.
AllChars<S, Allowed>Is every char of S a member of the Allowed union? The empty string is true.
NonEmptyAllChars<S, Allowed>AllChars, but the empty string is false โ the variant most predicates want.
And<A, B>Boolean conjunction over true | false.
Or<A, B>Boolean disjunction.
Not<A>Boolean negation.
KeepIf<B, S>The collapse step: keep S when B is true, else never. Turns a predicate into an S | never validator.
Length<S>Count the characters in S as a number literal.
ยง Numbers & ranges
IntRange<From, To>Half-open numeric-literal range โ From inclusive, To exclusive. Powers the bounded validators below.
IsNonNegativeNumber<S>Digits with an optional fractional part. No sign.
IsSignedDecimal<S>A non-negative number with an optional leading minus.
IsNumber<S>A decimal with an optional leading + or -. The broadest numeric shape.
IsPositiveInt<S>An integer โฅ 1 (rejects 0 and the empty string).
IsByte<S>Integer 0โ255 โ the RGB channel range.
IsNumber0To1<S>Number in 0โ1 inclusive โ the alpha / opacity range.
IsNumber0To100<S>Number in 0โ100 inclusive.
IsNumber0To360<S>Number in 0โ360 inclusive โ the hue-degree range.
IsNumber0To400<S>Number in 0โ400 inclusive.
IsPercent0To100<S>An N% literal whose N lands in 0โ100.
ยง CSS dimensions
IsLength<S>A number plus a CSS length unit โ px, rem, em, vh, cqmin, and the rest.
IsAngle<S>A number plus deg / grad / rad / turn.
IsTime<S>A number plus s / ms.
IsResolution<S>A number plus dpi / dpcm / dppx / x.
IsPercentage<S>Any N% literal (unbounded โ pair with IsPercent0To100 to clamp the range).
IsFlex<S>A non-negative Nfr grid flex value.
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.
ยง Parser combinators
StartsWith<S, P>Does S begin with the prefix P?
EndsWith<S, P>Does S end with the suffix P?
SplitByComma<S>Split on top-level commas, ignoring those nested in parens or brackets. Trims each token; keeps empties.
SplitBySpace<S>Split on top-level whitespace, paren-aware. Collapses runs (drops empties).
ParseFunction<S>Split the outer call into its name and raw args; never when S is not a call.
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.
Literal validator:const x = <S extends string>(v: S & XLiteral<S>): S => v
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")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
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"]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