#Is there a way to type a parameter to a class method using a decorator?

2 messages · Page 1 of 1 (latest)

devout marsh
#

Here is what my final design should look like

class myClass{
  @Decorator()
  method(arg){
     arg; // should be typed as string
  }
}

I understand this is not possible with decorators out of the box but I am thinking it may be possible by narrowing the type passed as the descriptor, the decorator returns a function that accepts a description, the type of which is TypedPropertyDescriptor<T> I am thinking if in the decorator I can somehow narrow the allowed descriptor (by explicitly defining T) it may be able to infer the type based on that, I am not sure if that is even possible and so far I have had no luck

I need this for a proof of concept api framework, the ideal API would look like this

@Controller('auth')
@Tags('auth')
class Auth extends BaseController{
  @Post('login')
  @Body(bodyValidator) // zod validator for the body
  async login(ctx){
    ctx.req.valid('json') // ctx should be a hono request ctx with the correct generics populated by the decorators
  }
}

To me this looks much cleaner than the existing chaining methods APIs or passing in arguments for data validators, If I can figure this out I could also add middleware and context support as well as extending classes to create sub modules

#

The end result will also need to accept a generic and be able to chain so we can have multiple decorators for different data and middleware, for example

@Body(bodyValidator)
@Use(ipAddressMiddleware)
@Query(queryParamsValidator, false) // false will make sure it is not validated
async login(ctx){
  ctx.req.valid('json') // type: z.infer<typeof bodyValidator>
  ctx.req.valid('query') // type: z.infer<typeof queryParamsValidator>
  ctx.var.ipAddress; // comes from ipAddressMiddleware
}

For the sake of this question I am assuming there is a simple way to pass the actual data, I could always use some context api like asyncLocalStorage so for now I am only concerned with the types