I have a system of sharing types between the backend in frontend which looks something like this in the controller:
@Controller()
export class MyController {
@ApplyRoute('GET /foo')
async findAll(
@Query() { name }: Routes['GET /foo']['query'], // repeated route name
): Promise<Routes['GET /foo']['response']> { // repeated route name
return { foo: true }
}
}
Note how 'GET /foo' appears 3 times: once to declare the http method/path, once to get the type of query parameters, and once to enforce the return type.
I'm looking for a way to somehow remove that repetition, but I can't seem to think of any way that plays nice with the decorators. Right now someone could use the path of one route and then use a different route's query or response, which is probably quite wrong.
How can this duplication of route names be removed?
For example, something that does what this totally invalid syntax implies:
@Controller()
export class MyController {
@ApplyRoute('GET /foo') {
async findAll(
@Query() { name }: CurrentRoute['query'],
): Promise<CurrentRoute['response']> {
return { foo: true }
}
}
}
For additional info, the plumbing works like this.
There is a type that defines all routes, and the types that route accepts and returns:
type Routes = {
'GET /foo': {
query: { name: string }
response: { foo: true }
}
'GET /bar': {
query: {},
response: { bar: true }
}
}
Then we have a little helper decorator which parses the route name to the @RequestMapping() decorator to set the http method and path for a controller method:
export function ApplyRoute(routeName: keyof Routes): MethodDecorator {
const [method, path] = routeName.split(' ') as ['GET' | 'POST', string]
return applyDecorators(
RequestMapping({ path, method: RequestMethod[method] }),
)
}