Hotscript
A library of composable functions for the type-level! Transform your TypeScript types in any way you want using functions you already know.
Install / Use
/learn @gvergnaud/HotscriptREADME
Higher-Order TypeScript (HOTScript)
A library of composable functions for the type level!
Transform your TypeScript types in any way you want using functions you already know.

Features
- Type-level higher-order functions (
Tuples.Map,Tuples.Filter,Objects.MapValues, etc). - Type-level pattern matching with
Match. - Performant math operations (
Numbers.Add,Numbers.Sub,Numbers.Mul,Numbers.Div, etc). - Custom "lambda" functions.
🚧 work in progress 🚧
Installation
You can find HotScript on npm:
npm install -D hotscript
HotScript is a work-in-progress library, so expect breaking changes in its API.
Examples
Transforming a list
Run this as a TypeScript Playground
<!-- prettier-ignore -->import { Pipe, Tuples, Strings, Numbers } from "hotscript";
type res1 = Pipe<
// ^? 62
[1, 2, 3, 4],
[
Tuples.Map<Numbers.Add<3>>, // [4, 5, 6, 7]
Tuples.Join<".">, // "4.5.6.7"
Strings.Split<".">, // ["4", "5", "6", "7"]
Tuples.Map<Strings.Prepend<"1">>, // ["14", "15", "16", "17"]
Tuples.Map<Strings.ToNumber>, // [14, 15, 16, 17]
Tuples.Sum // 62
]
>;
Defining a first-class function
Run this as a TypeScript Playground
import { Call, Fn, Tuples } from "hotscript";
// This is a type-level "lambda"!
interface Duplicate extends Fn {
return: [this["arg0"], this["arg0"]];
}
type result1 = Call<Tuples.Map<Duplicate>, [1, 2, 3, 4]>;
// ^? [[1, 1], [2, 2], [3, 3], [4, 4]]
type result2 = Call<Tuples.FlatMap<Duplicate>, [1, 2, 3, 4]>;
// ^? [1, 1, 2, 2, 3, 3, 4, 4]
Transforming an object type
Run this as a TypeScript Playground
import { Pipe, Objects, Booleans } from "hotscript";
// Let's compose some functions to transform an object type:
type ToAPIPayload<T> = Pipe<
T,
[
Objects.OmitBy<Booleans.Equals<symbol>>,
Objects.Assign<{ metadata: { newUser: true } }>,
Objects.SnakeCaseDeep,
Objects.Assign<{ id: string }>
]
>;
type T = ToAPIPayload<{
id: symbol;
firstName: string;
lastName: string;
}>;
// Returns:
type T = {
id: string;
metadata: { new_user: true };
first_name: string;
last_name: string;
};
Parsing a route path
Run this as a TypeScript Playground
https://user-images.githubusercontent.com/2315749/222081717-96217cd2-ac89-4e06-a942-17fbda717cd2.mp4
import { Pipe, Objects, Strings, ComposeLeft, Tuples, Match } from "hotscript";
type res5 = Pipe<
// ^? { id: string, index: number }
"/users/<id:string>/posts/<index:number>",
[
Strings.Split<"/">,
Tuples.Filter<Strings.StartsWith<"<">>,
Tuples.Map<ComposeLeft<[Strings.Trim<"<" | ">">, Strings.Split<":">]>>,
Tuples.ToUnion,
Objects.FromEntries,
Objects.MapValues<
Match<[Match.With<"string", string>, Match.With<"number", number>]>
>
]
>;
Make querySelector typesafe
Run this as a TypeScript Playground
import * as H from 'hotscript'
declare function querySelector<T extends string>(selector: T): ElementFromSelector<T> | null
interface Trim extends H.Fn {
return:
this["arg0"] extends `${infer Prev} ,${infer Next}` ?
H.$<Trim, `${Prev},${Next}`> :
this["arg0"] extends `${infer Prev}, ${infer Next}` ?
H.$<Trim, `${Prev},${Next}`> :
this["arg0"] extends `${infer Prev}:is(${infer El})${infer Rest}` ?
H.$<Trim, `${Prev}${El}${Rest}`> :
this["arg0"] extends `${infer Prev}:where(${infer El})${infer Rest}` ?
H.$<Trim, `${Prev}${El}${Rest}`> :
this["arg0"] extends `${infer El}(${string})${infer Rest}` ?
H.$<Trim, `${El}${Rest}`> :
this["arg0"] extends `${infer El}[${string}]${infer Rest}` ?
H.$<Trim, `${El}${Rest}`> :
this["arg0"]
}
type ElementFromSelector<T> = H.Pipe<T, [
Trim,
H.Strings.Split<' '>,
H.Tuples.Last,
H.Strings.Split<','>,
H.Tuples.ToUnion,
H.Strings.Split<":" | "[" | "." | "#">,
H.Tuples.At<0>,
H.Match<[
H.Match.With<keyof HTMLElementTagNameMap, H.Objects.Get<H._, HTMLElementTagNameMap>>,
H.Match.With<any, HTMLElement>
]>
]>
API
- [x] Core
- [x]
Pipe<Input, Fn[]>: Pipes a type through several functions. - [x]
PipeRight<Fn[], Input>: Pipe a type from right to left. - [x]
Call<Fn, ...Arg>: Call a type levelFnfunction. - [x]
Apply<Fn, Arg[]>: Apply several arguments to anFnfunction. - [x]
PartialApply<Fn, Arg[]>: Make anFnpartially applicable. - [x]
Compose<Fn[]>: ComposeFnfunctions from right to left. - [x]
ComposeLeft<Fn[]>: ComposeFnfunctions from left to right. - [x]
args,arg0,arg1,arg2,arg3: Access piped parameters (Useful in combination withObjects.Create). - [x]
_: Placeholder to partially apply any built-in functions, or functions created withPartialApply.
- [x]
- [x] Function
- [x]
ReturnType<FunctionType>: Extract the return type from a function type. - [x]
Parameters<FunctionType>: Extract the parameters from a function type as a tuple. - [x]
Parameter<N, FunctionType>: Extract the parameter at indexNfrom a function type. - [x]
MapReturnType<Fn, FunctionType>: Transform the return type of a function type using anFn. - [x]
MapParameters<Fn, FunctionType>: Transform the tuple of parameters of a function type using anFn.
- [x]
- [x] Tuples
- [x]
Create<X> -> [X]: Create a unary tuple from a type. - [x]
Partition<Fn, Tuple>: Using a predicateFn, turn a list of types into two lists[Passing[], Rejected[]]. - [x]
IsEmpty<Tuple>: Check if a tuple is empty. - [x]
Zip<...Tuple[]>: Zips several tuples together. For example. it would turn[[a,b,c], [1,2,3]]into[[a, 1], [b, 2], [c, 3]]. - [x]
ZipWith<Fn, ...Tuple[]>: Zip several tuples by calling a zipperFnwith one argument per input tuple. - [x]
Sort<Tuple>: Sorts a tuple of number literals. - [x]
Head<Tuple>: Returns the first element from a tuple type. - [x]
Tail<Tuple>: Drops the first element from a tuple type. - [x]
At<N, Tuple>: Returns theNth element from a tuple. - [x]
Last<Tuple>: Returns the last element from a tuple. - [x]
FlatMap<Fn, Tuple>: Calls anFnfunction returning a tuple on each element of the input tuple, and flattens all of the returned tuples into a single one. - [x]
Find<Fn, Tuple>: Finds an element from a tuple using a predicateFn. - [x]
Drop<N, Tuple>: Drops theNfirst element
- [x]
Related Skills
node-connect
338.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Writing Hookify Rules
83.4kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
review-duplication
99.3kUse this skill during code reviews to proactively investigate the codebase for duplicated functionality, reinvented wheels, or failure to reuse existing project best practices and shared utilities.
