I have an enum for http methods:
export enum HttpMethod {
GET = 'GET', POST = 'POST', /*...*/
}
Then I define a basic method type, that can have any HttpMethod
as key:
type Methods = {
[M in HttpMethod]?: any;
};
A basic Route type could use this Method type:
type Route<M extends Methods = any> = {
methods: M;
}
So I can define any route like:
interface AnyRoute extends Route<{
[HttpMethod.GET]: AnyRequestHandler;
}> {}
So far so good. Now I want to add a Validator
:
type Validator<R extends Route, M extends HttpMethod> = {/*...*/}
And only want to allow adding Method
s to the Validator
, that are defined in the Route
:
type RouteMethodValidators<R extends Route> = {
[M in keyof R['methods']]?: Validator<R, M>;
};
Although my IDE seems to understand it, I get the following errors:
Type 'M' does not satisfy the constrain 'HttpMethod'.
Type 'keyof R["methods"]' is not assignable to type 'HttpMethod'.
Is there any way I can tell typescript, that this is is definitely a member of HttpMethod
?
Your problem mostly lies here: type Route<M extends Methods = any>
First of all, a default value any
will result in M
being of type string
in RouteMethodValidator
because Route<any>['methods']
is any
and keyof any
is string
.
Now, changing the default value to Methods
still won't solve the problem because you do M extends Methods
which basically means that M
can have more keys than the ones defined in Methods
, i.e. more than are defined in HttpMethods
. But in Validator
you only allow values of HttpMethods
.
I believe your best option would be to make Route
not generic.
type Route = {
methods: Methods;
}
type RouteMethodValidators<R extends Route> = {
[M in HttpMethod]?: Validator<R, M>;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With