英文:
Getting class method argument types from indexed generic type
问题
class Example {
methodA(param1: string, param2: number) {}
methodB(): string {}
methodC(param1: boolean, param2: number): number {}
prop1: string = '';
}
function call<K extends keyof Example>(functionName: K, ...args: Parameters<Example[K]>): ReturnType<Example[K]> {
// Your implementation here...
}
你的代码看起来基本上是正确的,但是你可能需要确保 call
函数的实现与参数类型相匹配。在你的 call
函数中,Parameters<Example[K]>
和 ReturnType<Example[K]>
应该与指定的方法匹配,否则会导致类型错误。
如果你在 call
函数的实现中正确地使用了 args
,并且返回了与指定方法的返回类型相匹配的值,那么你的代码应该可以正常工作。如果你仍然遇到类型错误,请确保 call
函数的实现与方法的预期签名相匹配。
英文:
I have a class with some functions as well as a non-function property:
class Example {
methodA(param1: string, param2: number) {}
methodB(): string {}
methodC(param1: boolean, param2: number): number {}
prop1: string = '';
}
I want to write a method that would receive the class method name as a parameter and the corresponding method's arguments as the remaining parameters and also return the same data type as the specified class method. It would look like this:
call('methodA', 'a string', 123); // If the method has a void return type
let value = call('methodC', true, 456) // If the method has a non-void return type;
I can fetch the method names using keyof Example
as follows:
function call<K extends keyof Example>(functionName: K) {}
However, I am stuck at getting the corresponding method arguments and return type. My attempt has been as follows:
function call<K extends keyof Example>(functionName: K, ...args: Parameters<Example[K]>): ReturnType<Example[K]>
When I do this, I get an error stating that Type 'Example[K]' does not satisfy the constraint '(...args: any) => any'
.
When I use the indexed type on its own and without using the rest parameters
function call<K extends keyof Example>(functionName: K, args: Example[K])...
I can see that the correct function signature is expected as the args parameters, so I assumed that this function type satisfy the constraint expected by the Parameters<> utlity type. I have a similar issue with the ReturnType utility type.
How could I get Example[K]
to work as (...args: any) => void
?
答案1
得分: 0
以下是翻译好的部分:
你想要获取 Example
中属性值可调用的键。没有内置的实用程序类型可以为您完成此操作(请参阅 microsoft/TypeScript#48992 相关的功能请求),但您可以通过多种方式自己定义。这是一种方式,使用 键重映射:
type KeysMatching<T extends object, V> = keyof {
[K in keyof T as T[K] extends V ? K : never]: any
}
因此,KeysMatching<T, V>
将为您提供仅适用于 T
属性值可分配给 V
的那些键。因此,您可以像这样获取 Example
中可调用的键:
type CallableKeys = KeysMatching<Example, (...args: any) => any>;
// type CallableKeys = "methodA" | "methodB" | "methodC"
现在,您可以根据 CallableKeys
定义 call()
:
declare function call<K extends CallableKeys>(
functionName: K, ...args: Parameters<Example[K]> // okay
): ReturnType<Example[K]>;
并且错误会消失。
这种方法的优点是,如果将更多的非函数属性添加到 Example
类中,它会自动更新。
英文:
You want to get just the keys of Example
whose property values are callable. There is no built-in utility type that does this for you (see microsoft/TypeScript#48992 for the relevant feature request) but you can define your own in a number of ways. Here's one way, using key remapping:
type KeysMatching<T extends object, V> = keyof {
[K in keyof T as T[K] extends V ? K : never]: any
}
So KeysMatching<T, V>
will give you just those keys of T
whose property values are assignable to V
. And so you can get just the callable keys of Example
like this:
type CallableKeys = KeysMatching<Example, (...args: any) => any>;
// type CallableKeys = "methodA" | "methodB" | "methodC"
Now you can then define call()
in terms of CallableKeys
:
declare function call<K extends CallableKeys>(
functionName: K, ...args: Parameters<Example[K]> // okay
): ReturnType<Example[K]>;
and the error goes away.
This approach has the advantage of automatically updating if more non-function properties are added to the Example
class.
答案2
得分: 0
我已找到解决我的问题的方法,问题在于我使用的类还包含公共变量/属性,这些变量/属性会被keyof Example
类型捕捉到。当在Parameters<>
类型中使用它时,会引发错误,因为并非所有类属性都可调用。
解决方法是将keyof Example
包裹在Exclude<>
实用类型中,并指定需要排除的键。
例如,如果类声明如下:
class Example {
public prop1: string = '';
methodA(param1: string, param2: number) {}
methodB(): string {}
methodC(param1: boolean, param2: number): number {}
}
然后,可调用的键可以使用Exclude<keyof Example, 'prop1'>
来获取,结果是Parameters<Exclude<keyof Example, 'prop1'>>
是有效的。
英文:
I have found the solution to my issue, the problem was that the class I was using also contained public variables/properties and these are picked up by the keyof Example
type. When using this in a Parameters<>
type, it throws an error because not all the class properties are callable.
The solution was to enclose the keyof Example
inside an Exclude<>
utility type and specify which keys need to be excluded.
For example, if the class was declared as follows:
class Example {
public prop1: string = '';
methodA(param1: string, param2: number) {}
methodB(): string {}
methodC(param1: boolean, param2: number): number {}
}
then callable keys can be obtained using Exclude<keyof Example, 'prop1'>
resulting in Parameters<Exclude<keyof Example, 'prop1'>>
being valid.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论