Skip to content

Instantly share code, notes, and snippets.

@AlexJWayne
Created August 5, 2024 02:00
Show Gist options
  • Save AlexJWayne/a3d53d06baed48d4ac227d975312ce80 to your computer and use it in GitHub Desktop.
Save AlexJWayne/a3d53d06baed48d4ac227d975312ce80 to your computer and use it in GitHub Desktop.
// exported types will be available for you to import from compiled files
// to distinguish between objects ({}) and blocks, blocks have a colon before the opening brace (:{})
export type parseRoute = (route: string) => :{
// assign computations to variables like this
let parts = route.split("/"); // -> ["users", "<id:string>", "posts", "<index:number>"]
// last expression is the return value, like in Rust
parts
// method chaining!
.filter((part) => part.startsWith("<")) // -> ["<id:string>", "<index:number>"]
.map((part) => match part {
// infer subparts of the expression during pattern matching
`<${infer name}:${infer ty}>` -> [name, ty]
}) // -> [["id", "string"], ["index", "number"]]
.toUnion() // -> ["id", "string"] | ["index", "number"]
.fromEntries() // -> { id: "string"; index: "number" }
.mapValues((ty) => match ty {
"string" -> string,
"number" -> number
}) // -> { id: string; index: number }
}
type params = parseRoute("/users/<id:string>/posts/<index:number>")
// ^?
// { id: string; index: number; }
// Add tests alongside your code
#[test] :{
AssertEqual(
parseRoute("/users/<id:string>/posts/<index:number>"),
{ id: string, index: number }
)
AssertEqual(
parseRoute("/users/noParams"),
{}
)
}
import {
type Call,
type Fn,
type PartialApply,
type Apply,
type arg,
type Booleans,
} from "tartak/hot";
import {
type Split,
type StartsWith,
type Filter,
type Map,
type ToUnion,
type FromEntries,
type MapValues,
type Expect,
} from "tartak/prelude";
interface lambda_temp_1 extends Fn {
return: StartsWith<this["arg1"], "<">;
}
interface lambda_temp_2 extends Fn {
return: this["arg1"] extends `<${infer name}:${infer ty}>`
? [name, ty]
: undefined;
}
interface lambda_temp_3 extends Fn {
return: this["arg1"] extends "string"
? string
: this["arg1"] extends "number"
? number
: undefined;
}
interface lambda_temp_4 extends Fn {
return: Split<this["arg1"], "/"> extends infer parts extends Split<
this["arg1"],
"/"
>
? MapValues<
FromEntries<
ToUnion<
Map<
Filter<
parts,
[parts, this["arg1"]] extends infer scope
? PartialApply<lambda_temp_1, [scope]>
: never
>,
[parts, this["arg1"]] extends infer scope
? PartialApply<lambda_temp_2, [scope]>
: never
>
>
>,
[parts, this["arg1"]] extends infer scope
? PartialApply<lambda_temp_3, [scope]>
: never
>
: never;
}
export type parseRouteHOT = PartialApply<lambda_temp_4, [[]]>;
export type parseRoute<route extends string> = Call<parseRouteHOT, route>;
type params =
"/users/<id:string>/posts/<index:number>" extends infer temp_5 extends "/users/<id:string>/posts/<index:number>"
? (
temp_5 extends any ? Apply<parseRouteHOT, [temp_5]> : never
) extends never
? PartialApply<parseRouteHOT, [temp_5]>
: Apply<parseRouteHOT, [temp_5]>
: never;
// test
namespace test {
type temp_7 = Expect<
Call<
Booleans.Equals<
"/users/<id:string>/posts/<index:number>" extends infer temp_6 extends "/users/<id:string>/posts/<index:number>"
? (
temp_6 extends any ? Apply<parseRouteHOT, [temp_6]> : never
) extends never
? PartialApply<parseRouteHOT, [temp_6]>
: Apply<parseRouteHOT, [temp_6]>
: never,
{ id: string; index: number }
>
>
>;
type temp_9 = Expect<
Call<
Booleans.Equals<
"/users/noParams" extends infer temp_8 extends "/users/noParams"
? (
temp_8 extends any ? Apply<parseRouteHOT, [temp_8]> : never
) extends never
? PartialApply<parseRouteHOT, [temp_8]>
: Apply<parseRouteHOT, [temp_8]>
: never,
{}
>
>
>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment