Skip to content

Instantly share code, notes, and snippets.

@sina-salahshour
Created May 13, 2025 13:21
Show Gist options
  • Select an option

  • Save sina-salahshour/80048d8e759bd2f88cea6c0a335fad0d to your computer and use it in GitHub Desktop.

Select an option

Save sina-salahshour/80048d8e759bd2f88cea6c0a335fad0d to your computer and use it in GitHub Desktop.
RequestFetcherBuilder
import {z} from 'zod'
type getParams<T> = T extends `${infer Path}/?${infer Search}` ?
[
...getPathParams<Path>,
...getSearchParams<`?${Search}`>
]: T extends `${infer Path}?${infer Search}` ?
[
...getPathParams<Path>,
...getSearchParams<`?${Search}`>
]: T extends `${infer Path}/` ?
[
...getPathParams<Path>,
]: T extends `${infer Path}` ?
[
...getPathParams<Path>,
]: []
type RequestMethod = "get" | "post" | "patch" | "put" | "delete"
type getPathParams<T> = T extends `${infer Start}:${infer Item}/${infer End}` ?
[Item, ...getPathParams<End>] :
T extends `${infer Start}:${infer Item}:${infer End}` ?
[Item, ...getPathParams<`:${End}`>] :
T extends `${infer Start}:${infer Item}` ?
[Item] : []
type getSearchParams<T> =
T extends `${infer Start}?${infer Item}?${infer End}` ?
[Item, ...getSearchParams<`?${End}`>] :
T extends `${infer Start}?${infer Item}` ?
[Item] : []
type tupleToObject<T extends string[]> = {
[key in T[number]]: string
}
type StringLiteral<T> = T extends string ? string extends T ? never : T : never;
function createApi<Url, RequestBody extends z.ZodType | void = void>(method: RequestMethod, url:StringLiteral<Url>, bodySchema?: RequestBody): <Response, Request = void>() => (params: getParams<Url> extends [] ? Request extends void ? RequestBody extends z.ZodType ? z.infer<RequestBody> : void : Request : tupleToObject<getParams<Url>>, body: getParams<Url> extends [] ? void : Request extends void ? RequestBody extends z.ZodType ? z.infer<RequestBody> : void : Request) => Promise<Response> {
throw new Error()
}
const loginSchema = z.object({
username: z.string(),
password: z.string()
})
type LoginResponse = {success:true, data: {username:string,name:string}} | {success:false}
const x = createApi("get", "/user/login:id", loginSchema)<LoginResponse>()
const res = await x({id:"2"},{
password:"1234",
username:"1234"
})
const x2 = createApi("get", "/user/login", loginSchema)<LoginResponse>()
const res2 = await x2({
password:"1234",
username:"1234"
})
const x3 = createApi("get", "/user/login")<LoginResponse, {username:string,password:string}>()
const res3 = await x3({
password:"1234",
username:"1234"
})
const x4 = createApi("delete", "/user/login")<LoginResponse>()
const res4 = await x4()
const signupApi = createApi("post", "/user/:user/:company?page?search", loginSchema)<LoginResponse>()
const result = await signupApi({
company:"1",
page: "2",
search: "4",
user: ""
}, {
username: "1",
password: "2"
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment