Skip to content

Instantly share code, notes, and snippets.

@dietergoetelen
Created November 11, 2022 12:38
Show Gist options
  • Save dietergoetelen/9cfdd4e7bffbdb2fa44a7f00915dcc66 to your computer and use it in GitHub Desktop.
Save dietergoetelen/9cfdd4e7bffbdb2fa44a7f00915dcc66 to your computer and use it in GitHub Desktop.
Strong typed endpoint
type Split<S extends string, D extends string> = S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [S];
type Cast<S extends string> = S extends 'string' ? string : S extends 'number' ? number : never;
type Urlify<S extends string> = S extends `{${infer TKey}:${infer TType}}` ? [TKey, Cast<TType>] : S extends `{${infer TKey}}` ? [TKey, string | number] : S
type UrlifyEach<V, L extends string[] = []> =
V extends []
? L
: V extends [string]
? [...L, Urlify<V[0]>]
: V extends [string, ...infer R]
? UrlifyEach<R, [...L, Urlify<V[0]>]>
: []
type ConvertTuple<TValue, TResult extends Record<string, unknown>> = TValue extends [infer TKey, infer TType] ? TKey extends string ? {[Key in keyof TResult]: TResult[Key]} & {[R in TKey]: TType} : TResult : TResult
type GetParams<TValue extends Array<any>, TResult extends Record<string, unknown> = {}> =
TValue extends []
? TResult
: TValue extends [infer R]
? R extends string
? TResult
: ConvertTuple<R, TResult>
: TValue extends [infer T, ...infer R]
? GetParams<R, ConvertTuple<T, TResult>>
: TResult
type Params<T extends string> = GetParams<UrlifyEach<Split<T, '/'>>>
function endpoint<TUrl extends string>(url: TUrl): keyof Params<TUrl> extends [] ? () => string : (params: Params<TUrl>) => string {
return (params?: Params<TUrl>) => {
const toParse = params ?? {}
const keys = Object.keys(toParse)
return ''
}
}
const r1 = endpoint('/')()
const r2 = endpoint('/foo/bar')()
const r3 = endpoint('/foo/{id}')({id: ''})
const r4 = endpoint('/foo/{id:number}')({id: 1})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment