function Middleware<T extends Function>(middleware: Array<{ funcs: Array<keyof T['prototype']>, class: T }>) {
}
class TestValidation {
Test() { }
}
class FilterValidation {
Filter() { }
}
I am defining Middleware fonkisyon and I want to use giving class functions as string. But not working.
example usage
Middleware([
{ funcs: ['Test'], class: TestValidation },
{ funcs: ['Filter'], class: FilterValidation}
])
this code givin error
Type '"Filter"' is not assignable to type 'keyof TestValidation'
how can I fix this problem?
2
Answers
To fix the TypeScript type problem in your code, you can make a small modification. Instead of defining funcs as an array of keyof T[‘prototype’], you can define it as an array of strings that represent the function names. Here’s an updated version of your code:
By defining funcs as Array<keyof T[‘prototype’]> | string[], it allows both keys of the prototype and string representations of the function names. This change will resolve the error you were encountering.
Note: In the example usage, make sure you have defined the TestValidation and FilterValidation classes with their respective functions (Test and Filter).
One approach is to make
Middleware
generic in a type parameterT
corresponding to the tuple type of instance types constructed by theclass
property of themiddleware
array. So if you callMiddleware([{funcs: [], class: Class1}, {funcs: [], class: Class2}])
, whereClass1
andClass2
are class constructors of types namedClass1
andClass2
respectively, thenT
would be the type[Class1, Class2]
.And we’d make the
middleware
parameter be of a mapped type overT
, such that each element ofmiddleware
takes on a type related to the corresponding element ofT
. For each numeric indexI
from the keys ofT
, theclass
property should be a construct signature forT[I]
(the element ofT
at keyI
), while thefuncs
property should be an array of keys ofT[I]
whose properties are functions.We can write it like this:
where
KeysMatching<T, V>
is a utility type to get the property keys ofT
whose property values are assignable toV
. One possible definition isSee In TypeScript, how to get the keys of an object type whose values are of a given type? for more information about how
KeysMatching
works.Oh, and the
middleware
parameter’s type is wrapped in a variadic tuple type like[...
+]
to give the compiler a hint that we wantT
to be inferred as a tuple and not an unordered array.Okay, let’s test it:
Looks good. Let’s test it on an example that fails:
That fails because
"a"
and"b"
are keys ofFoo
whose values are not functions. Only"c"
is accepted. So this solution works for both accepting desirable inputs and rejecting undesirable ones.Playground link to code