When working with generated APIs, such as openapi-fetch, our code may look something like this:
import {paths} from "./the-generated-types";
import createClient from "openapi-fetch";
const client = createClient<paths>();
// Using the client:
client.GET("/blogposts/{post_id}", {
params: {
path: { post_id: "my-post" },
query: { version: 2 },
},
});
// To maintain code structure and modularity, we can define a module interface:
export async function getBlogPostById(args: ??) : Promise< ???> {
}
For illustration purposes, here are some typings:
type Paths = "/a" | "/b" | "/c";
type PathToMethodMap = {
"/a": {
GET: (query: {search: string}) => {id: string; value: string};
},
"/b": {
GET: (query: {search: string}) => {id: string; value: string};
}
"/c": {
GET: (query: {search: string}) => {id: string; value: string};
PATCH: (body: {id: string, value: string}) => {id: string; value: string};
}
}
function getClient<T extends Paths>(path: T ) : PathToMethodMap[T] {
}
getClient("/a").GET({search: "hello"})
getClient("/c").PATCH({id: "a", value: "b"})
We can implement a function like this:
function patchC(...args: Parameters<PathToMethodMap["/c"]["PATCH"]>)
: ReturnType<PathToMethodMap["/c"]["PATCH"]>{
}
However, in practical scenarios, these typings tend to be complex and cumbersome.
Is it possible to achieve a typing like this?
function alternativePatchC(...args: Parameters<typeof getClient[WHEN CALLED WITH "/c"]["PATCH"]>)
: ReturnType<typeof getClient[WHEN CALLED WITH "/c"]["PATCH"]>{
}