type PathConverter

= (params: P) => string type routes = { boards: { GET: { pathParams: {} bodyParams: {} }, POST: { pathParams: {} bodyParams: { title: string } } }, board: { GET: { pathParams: { id: number } bodyParams: {} }, PATCH: { pathParams: { id: number } bodyParams: { title: string } } } } type HttpVerbs = 'GET' | 'POST' | 'PATCH' type Verbs = keyof R & HttpVerbs type Resources = keyof routes function f< V extends Verbs, R extends Resources, P extends routes[R][V] extends { pathParams: infer PP, bodyParams: infer BP } ? PP & BP : {} >(verb: V, name: R, params: P) { return verb + name + JSON.stringify(params) } const updateBoard = ['PATCH', 'board'] f('PATCH', 'board', { id: 1, title: 'hi' })