type HttpVerbs = 'GET' | 'POST' | 'PATCH' | 'DELETE' const boards = { path: ({ id }: { id: number }) => `/boards/${id}` } as { path?: ({ id: number}) => string Methods?: { PATCH: { names: { id: number } params: { title: string } } DELETE: { names: { id: number } } } } type Resource = { path?: (names: any, opts?: any) => string Methods?: { [verb in HttpVerbs]?: any } } function f< M extends keyof Exclude, T extends Resource, P extends Exclude[M] >(method: M, { path }: T, params: P): string { return method + path(params) } type P = Exclude<(typeof boards)['Methods'], undefined>['DELETE'] // const params = { id: 1, title: 'hi' } const params = { id: 1 } type AP = typeof params type XP = Exclude extends never ? P : never f('PATCH', boards, { names: { id: 1 }, params: { title: 'hi' } }) f('PATCH', boards, { params: { title: 'hi' } }) f('DELETE', boards, { names: { id: 1 } }) f('DELETE', boards, { names: { id: 1 }, params: { title: 'hi' } }) f('GET', boards, { names: { id: 1 } }) f('FUGA', boards, { names: { id: 1 }, params: { title: 'hi' } })