Awesome
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
- Core
-
Pipe<Input, Fn[]>
: Pipes a type through several functions. -
PipeRight<Fn[], Input>
: Pipe a type from right to left. -
Call<Fn, ...Arg>
: Call a type levelFn
function. -
Apply<Fn, Arg[]>
: Apply several arguments to anFn
function. -
PartialApply<Fn, Arg[]>
: Make anFn
partially applicable. -
Compose<Fn[]>
: ComposeFn
functions from right to left. -
ComposeLeft<Fn[]>
: ComposeFn
functions from left to right. -
args
,arg0
,arg1
,arg2
,arg3
: Access piped parameters (Useful in combination withObjects.Create
). -
_
: Placeholder to partially apply any built-in functions, or functions created withPartialApply
.
-
- Function
-
ReturnType<FunctionType>
: Extract the return type from a function type. -
Parameters<FunctionType>
: Extract the parameters from a function type as a tuple. -
Parameter<N, FunctionType>
: Extract the parameter at indexN
from a function type. -
MapReturnType<Fn, FunctionType>
: Transform the return type of a function type using anFn
. -
MapParameters<Fn, FunctionType>
: Transform the tuple of parameters of a function type using anFn
.
-
- Tuples
-
Create<X> -> [X]
: Create a unary tuple from a type. -
Partition<Fn, Tuple>
: Using a predicateFn
, turn a list of types into two lists[Passing[], Rejected[]]
. -
IsEmpty<Tuple>
: Check if a tuple is empty. -
Zip<...Tuple[]>
: Zips several tuples together. For example. it would turn[[a,b,c], [1,2,3]]
into[[a, 1], [b, 2], [c, 3]]
. -
ZipWith<Fn, ...Tuple[]>
: Zip several tuples by calling a zipperFn
with one argument per input tuple. -
Sort<Tuple>
: Sorts a tuple of number literals. -
Head<Tuple>
: Returns the first element from a tuple type. -
Tail<Tuple>
: Drops the first element from a tuple type. -
At<N, Tuple>
: Returns theN
th element from a tuple. -
Last<Tuple>
: Returns the last element from a tuple. -
FlatMap<Fn, Tuple>
: Calls anFn
function returning a tuple on each element of the input tuple, and flattens all of the returned tuples into a single one. -
Find<Fn, Tuple>
: Finds an element from a tuple using a predicateFn
. -
Drop<N, Tuple>
: Drops theN
first elements from a tuple. -
Take<N, Tuple>
: Takes theN
first elements from a tuple. -
TakeWhile<Fn, Tuple>
: Take elements while theFn
predicate returnstrue
. -
GroupBy<Fn, Tuple>
: Transform a list into an object containing lists. TheFn
function takes each element and returns the key it should be added to. -
Join<Str, Tuple>
: Joins several strings together using theStr
separator string. -
Map<Fn, Tuple>
: Transforms each element in a tuple. -
Filter<Fn, Tuple>
: Removes elements from a tuple if theFn
predicate function doesn't returntrue
. -
Reduce<Fn, Init, Tuple>
: Iterates over a tuple a reduce it to a single function using a reducerFn
. -
ReduceRight<Fn, Init, Tuple>
: likeReduce
, but starting from the end of the list. -
Reverse<Tuple>
: Reverses the tuple. -
Every<Fn, Tuple>
: Checks if all element passes theFn
predicate. -
Some<Fn, Tuple>
: Checks if at least one element passes theFn
predicate. -
SplitAt<N, Tuple>
: Split a tuple into a left and a right tuple using an index. -
ToUnion<Tuple>
: Turns a tuple into a union of elements. -
ToIntersection<Tuple>
: Turns a tuple into an intersection of elements. -
Prepend<X, Tuple>
: Adds a type at the beginning of a tuple. -
Append<X, Tuple>
: Adds a type at the end of a tuple. -
Concat<T1, T2>
: Merges two tuples together. -
Min<Tuple>
: Returns the minimum number in a list of number literal types. -
Max<Tuple>
: Returns the maximum number in a list of number literal types. -
Sum<Tuple>
: Add all numbers in a list of number literal types together.
-
- Object
-
Readonly<Obj>
: Makes all object keysreadonly
. -
Mutable<Obj>
: Removesreadonly
from all object keys. -
Required<Obj>
: Makes all keys required. -
Partial<Obj>
: Makes all keys optional. -
ReadonlyDeep<Obj>
: Recursively makes all object keysreadonly
. -
MutableDeep<Obj>
: Recursively removesreadonly
from all object keys. -
RequiredDeep<Obj>
: Recursively makes all keys required. -
PartialDeep<Obj>
: Recursively makes all keys optional. -
Update<Path, Fn | V, Obj>
: Immutably update an object's field under a certain path. Paths are dot-separated strings:a.b.c
. -
Record<Key, Value>
: Creates an object type with keys of typeKey
and values of typeValue
. -
Keys<Obj>
: Extracts the keys from an object typeObj
. -
Values<Obj>
: Extracts the values from an object typeObj
. -
AllPaths<Obj>
: Extracts all possible paths of an object typeObj
. -
Create<Pattern, X>
: Creates an object of type Pattern with values of type X. -
Get<Path, Obj>
: Gets the value at the specified pathPath
in the objectObj
. -
FromEntries<[Key, Value]>
: Creates an object from a union of key-value pairs. -
Entries<Obj>
: Extracts the union of key-value pairs from an object typeObj
. -
MapValues<Fn, Obj>
: Transforms the values of an object typeObj
using a mapper functionFn
. -
MapKeys<Fn, Obj>
: Transforms the keys of an object typeObj
using a mapper functionFn
. -
Assign<...Obj>
: Merges multiple objects together. -
Pick<Key, Obj>
: Picks specific keysKey
from an object typeObj
. -
PickBy<Fn, Obj>
: Picks keys from an object typeObj
based on a predicate functionFn
. -
Omit<Key, Obj>
: Omits specific keysKey
from an object typeObj
. -
OmitBy<Fn, Obj>
: Omits keys from an object typeObj
based on a predicate functionFn
. -
CamelCase<Obj>
: Converts the keys of an object typeObj
to camelCase. -
CamelCaseDeep<Obj>
: Recursively converts the keys of an object typeObj
to camelCase. -
SnakeCase<Obj>
: Converts the keys of an object typeObj
to snake_case. -
SnakeCaseDeep<Obj>
: Recursively converts the keys of an objecttype
Obj to snake_case. -
KebabCase<Obj>
: Converts the keys of an object typeObj
to kebab-case. -
KebabCaseDeep<Obj>
: Recursively converts the keys of an object type Obj to kebab-case.
-
- Union
-
Map<Fn, U>
: Transforms each member of a union typeU
using a mapper functionFn
. -
Extract<T, U>
: Extracts the subset of a union typeU
that is assignable to typeT
. -
ExtractBy<Fn, U>
: Extracts the subset of a union typeU
that satisfies the predicate functionFn
. -
Exclude<T, U>
: Excludes the subset of a union typeU
that is assignable to typeT
. -
ExcludeBy<Fn, U>
: Excludes the subset of a union typeU
that satisfies the predicate functionFn
. -
NonNullable<U>
: Removes null and undefined from a union typeU
. -
ToTuple<U>
: Converts a union typeU
to a tuple type. -
ToIntersection<U>
: Converts a union typeU
to an intersection type.
-
- String
-
Length<Str>
: Returns the length of a string typeStr
. -
TrimLeft<Char, Str>
: Removes the specified character from the left side of a string typeStr
. -
TrimRight<Char, Str>
: Removes the specified character from the right side of a string typeStr
. -
Trim<Char, Str>
: Removes the specified character from both sides of a string typeStr
. -
Join<Sep, Str>
: Joins multiple string typeStr
with a separatorSep
. -
Replace<From, To, Str>
: Replaces all occurrences of a substringFrom
with another substringTo
in a string typeStr
. -
Slice<Start, End, Str>
: Extracts a portion of a string typeStr
from indexStart
to indexEnd
. -
Split<Sep, Str>
: Splits a string typeStr
into a tuple of substrings using a separatorSep
. -
Repeat<N, Str>
: Repeats a string typeStr
N
times. -
StartsWith<S, Str>
: Checks if a string typeStr
starts with a substringS
. -
EndsWith<E, Str>
: Checks if a string typeStr
ends with a substringE
. -
ToTuple<Str>
: Converts a string typeStr
to a tuple type. -
ToNumber<Str>
: Converts a string typeStr
to a number type. -
ToString<T>
: Converts any literal typeT
to a string literal type. -
Prepend<Start, Str>
: Prepends a string typeStart
to the beginning of a string typeStr
. -
Append<End, Str>
: Appends a string typeEnd
to the end of a string typeStr
. -
Uppercase<Str>
: Converts a string typeStr
to uppercase. -
Lowercase<Str>
: Converts a string typeStr
to lowercase. -
Capitalize<Str>
: Capitalizes the first letter of a string typeStr
. -
Uncapitalize<Str>
: Converts the first letter of a string typeStr
to lowercase. -
SnakeCase<Str>
: Converts a string typeStr
to snake_case. -
CamelCase<Str>
: Converts a string typeStr
to camelCase. -
KebabCase<Str>
: Converts a string typeStr
to kebab-case. -
Compare<Str1, Str2>
: Compares two string typesStr1
andStr2
and returns a number indicating their relative order. -
Equal<Str1, Str2>
: Checks if two string typesStr1
andStr2
are equal. -
NotEqual<Str1, Str2>
: Checks if two string typesStr1
andStr2
are not equal. -
LessThan<Str1, Str2>
: Checks ifStr1
is less thanStr2
in lexicographical order. -
LessThanOrEqual<Str1, Str2>
: Checks ifStr1
is less than or equal toStr2
in lexicographical order. -
GreaterThan<Str1, Str2>
: Checks ifStr1
is greater thanStr2
in lexicographical order. -
GreaterThanOrEqual<Str1, Str2>
: Checks ifStr1
is greater than or equal toStr2
in lexicographical order.
-
- Number
-
Add<N, M>
: Adds two number typesN
andM
. -
Multiply<N, M>
: Multiplies two number typesN
andM
. -
Subtract<N, M>
: Subtracts the number typeM
fromN
. -
Negate<N>
: Negates a number typeN
by changing its sign. -
Power<N, M>
: Raises a number typeN
to the power ofM
. -
Div<N, M>
: Divides a number typeN
byM
. -
Mod<N, M>
: Calculates the remainder of dividing a number typeN
byM
. -
Abs<N>
: Returns the absolute value of a number typeN
. -
Compare<N, M>
: Compares two number typesN
andM
and returns a number indicating their relative order. -
GreaterThan<N, M>
: Checks if the number typeN
is greater thanM
. -
GreaterThanOrEqual<N, M>
: Checks if the number typeN
is greater than or equal toM
. -
LessThan<N, M>
: Checks if the number typeN
is less thanM
. -
LessThanOrEqual<N, M>
: Checks if the number typeN
is less than or equal toM
.
-
- Boolean
-
And<Bool1, Bool2>
: Performs a logical AND operation between two boolean typesBool1
andBool2
. -
Or<Bool1, Bool2>
: Performs a logical OR operation between two boolean typesBool1
andBool2
. -
XOr<Bool1, Bool2>
: Performs a logical XOR (exclusive OR) operation between two boolean typesBool1
andBool2
. -
Not<Bool>
: Performs a logical NOT operation on a boolean typeBool
. -
Extends<A, B>
: Checks if typeA
extends or is equal to typeB
. -
Equals<A, B>
: Checks if typeA
is equal to typeB
. -
DoesNotExtend<A, B>
: Checks if typeA
does not extend typeB
.
-