我试图基于另一个通用类型声明一个通用类型,但没有成功。
目标是编写我自己的测试框架,并根据另一个参数(方法)键入一些参数。
type Arguments<T> = T extends (...args: infer U) => any ? U : never;
// my custom test method
const methodCall = <T extends (...args: any) => any>(args: {
method: T;
response: ReturnType<T>;
myArguments: Arguments<T>;
}): boolean => {
const { method, myArguments, response } = args;
return method.apply(null, myArguments) === response;
};
const test1 = (toto: string) => {
return toto === "success";
};
// usage of my custom function
methodCall({
method: test1,
myArguments: ["fail"],
response: false
});
// this is what I want to type
interface MyHelpers {
methodCall: any // HOW TO TYPE THIS?
methodCall2: (args: { flag: boolean }) => boolean;
}
// I would expose only the helpers object
const helpers = (): MyHelpers = {
methodCall: <T extends (...args: any) => any>(args: {
method: T;
response: ReturnType<T>;
myArguments: Arguments<T>;
}): boolean => {
const { method, myArguments, response } = args;
return method.apply(null, myArguments) === response;
},
methodCall2: (args: { flag: boolean }): boolean => {
return args.flag;
}
};
我期望另一个调用助手的对象能够像在助手中声明的那样键入helpers().methodCall(...)
。不能与any
一起使用。
可以在here处找到游乐场。
谢谢!
答案 0 :(得分:1)
如果我理解正确的话,您就很亲密。您可以在函数语法(在其中定义methodCall
的签名,就好像您在定义函数实现那样)和属性语法(在其中将methodCall
定义为恰好是lambda的属性)之间进行选择,这与您拥有的方式差不多)。
如果使用函数语法,请在尖括号(<>
),括号之间的参数列表以及冒号后的返回类型中定义通用名称;就像您要定义的函数没有主体一样。如果使用属性语法,那么您将定义一个lambda,并在尖括号中加上通用名称,在括号之间添加参数列表,并在粗体箭头(=>
之后的返回类型;您要通过该名称定义属性,并将类型-a function type-放在冒号之后。两种方法都可以为您服务。
(我还从您的自定义Arguments
实用程序类型切换为the undocumented Parameters
built-in。)
interface MyHelpers {
methodCall<T extends (...args: any) => any>(args: {
method: T;
response: ReturnType<T>;
myArguments: Parameters<T>;
}): boolean;
methodCall2: (args: { flag: boolean }) => boolean;
}
interface MyHelpersWithObjectSyntax {
methodCall: <T extends (...args: any) => any>(args: {
method: T;
response: ReturnType<T>;
myArguments: Parameters<T>;
}) => boolean;
methodCall2: (args: { flag: boolean }) => boolean;
}