Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
type True = 'true'
type False = 'false'
type Bool = True | False
type If<B extends Bool, IfTrue, IfFalse> = {
true: IfTrue
false: IfFalse
}[B]
type Not<B extends Bool> = If<B, False, True>
type And<B1 extends Bool, B2 extends Bool> = If<B1, B2, False>
type Test<IfAtMilano extends Bool, IfIsDrunk extends Bool> =
If<And<IfAtMilano, IfIsDrunk>,
"Ciao MilanoTS! Bella Festa!",
"Dove sono?">
type Run = Test<True, False>
type Zero = {
isZero: True
prevNat: never
}
type Succ<N extends Nat> = {
isZero: False,
prevNat: N
}
type Nat = Zero | Succ<any>
type One = Succ<Zero>
type Two = Succ<One>
type IsZero<N extends Nat> = N["isZero"]
type Prev<N extends Nat> = N["prevNat"]
/**
* for(let i = 10; i != 0; i--)
*/
type ForLoop<N extends Nat> = If<IsZero<N>, "Batman!", {NaNa: ForLoop<Prev<N>>}>
/**
* while(i != 0){
* if(i = 0){
* v = "Batman!"
* }else{
* v = {NaNa: v}
* }
* }
*/
type Test2 = ForLoop<Succ<Succ<Succ<Succ<Succ<Succ<Succ<Zero>>>>>>>>
type AddNat<N1 extends Nat, N2 extends Nat> = {
true: N2
false: Succ<AddNat<Prev<N1>, N2>>
}[IsZero<N1>]
// 1 + 10
// (0 + 10) + 1
type Four = AddNat<Two, Two>
declare const a: Test2
a.NaNa.NaNa.NaNa.NaNa.NaNa.NaNa.NaNa
type HListEmpty = {
isEmpty: True
item: never
nextList: never
}
type HListNextItem<V, L extends HList> = {
isEmpty: False
item: V
nextList: L
}
type HList = HListEmpty | HListNextItem<any, any>
type HListIsEmpty<L extends HList> = L["isEmpty"]
type HListItem<L extends HList> = L["item"]
type HListNextList<L extends HList> = L["nextList"]
type HListConcat<L1 extends HList, L2 extends HList> = {
true: L2,
false: HListNextItem<HListItem<L1>, HListConcat<HListNextList<L1>, L2>>
}[HListIsEmpty<L1>]
type TestList = HListNextItem<"Primo", HListNextItem<"due", HListNextItem<"lol", HListEmpty>>>
type Test3<L extends HList> = {
true: True,
false: {[K in L["item"]]: Test3<L["nextList"]>}
}[L["isEmpty"]]
type RunProg = Test3<TestList>
declare const ab: RunProg
ab.Primo.due.lol // => 'true'
type RouteLiteral<N extends string> = string
type RouteCapture<N extends string> = { name: N}
type RouteSegment = RouteLiteral<string> | RouteCapture<string>
type Route = HList
type RouteBuilder<R extends Route> = {
route: R
addLiteral<N extends string>(literal: N): RouteBuilder<HListConcat<R, HListNextItem<RouteLiteral<N>, HListEmpty>>>
addCapture<N extends string>(literal: N): RouteBuilder<HListConcat<R, HListNextItem<RouteCapture<N>, HListEmpty>>>
}
type RouteToCapture<R extends Route, P = {}> = {
true: P
false: RouteToCapture<HListNextList<R>, P & (HListItem<R> extends RouteCapture<string> ? {[K in HListItem<R>["name"]]: string} : P)>
}[HListIsEmpty<R>]
type RouteToRequest<R extends Route> = {
input: RouteToCapture<R>
}
type App<RM extends {[K: string]: Route}> = {
routes: RM
addRoute<N extends string, R extends Route>(name: N, fn: (rb: RouteBuilder<HListEmpty>) => RouteBuilder<R>): App<RM & {[K in N]: R}>
addHandler<N extends keyof RM>(name: N, handler: (request: RouteToRequest<RM[N]>) => string): App<RM>
}
declare const app: App<{}>
const myApp = app
.addRoute("postsIndex", url => url
.addLiteral("posts")
.addLiteral("index"))
.addRoute("postView", url => url
.addLiteral("posts")
.addCapture("post_id")
.addCapture("access_token")
.addLiteral("view"))
.addHandler("postsIndex", req => req.input.post_id)
.addHandler("postView", req => req.input.post_id)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment