Javascript 按对象的键/值键入脚本动态函数
是否有一种基于初始接口设置函数的方法?我有一堆ListofFunction和等量的包含函数类型的接口。我想创建一个返回自定义钩子的工厂。这样做的目的是节省大量代码,使编辑和向所有钩子添加特性变得轻而易举Javascript 按对象的键/值键入脚本动态函数,javascript,reactjs,typescript,factory-pattern,Javascript,Reactjs,Typescript,Factory Pattern,是否有一种基于初始接口设置函数的方法?我有一堆ListofFunction和等量的包含函数类型的接口。我想创建一个返回自定义钩子的工厂。这样做的目的是节省大量代码,使编辑和向所有钩子添加特性变得轻而易举 FunctionInterface是所有函数名及其返回值 listOfFunctions是一个设置函数(实际代码有一个配置),它返回一个包含函数列表的对象 chosenfunction是一个将在钩子中返回的函数,它允许我与其中一个listoff函数交互。这意味着参数(如果需要)。真正的应用程序中
FunctionInterface
是所有函数名及其返回值
listOfFunctions
是一个设置函数(实际代码有一个配置),它返回一个包含函数列表的对象
chosenfunction
是一个将在钩子中返回的函数,它允许我与其中一个listoff函数交互。这意味着参数(如果需要)。真正的应用程序中的函数是承诺,将设置钩子的状态。在本例中,我只返回一个值并设置state
A) 这是否可以使用funcObject[funcName]()
并创建一个要用typescript调用的函数?这将需要添加或不添加参数的能力
B) 有没有办法获取函数类型的返回值?所以在这个例子中:
类型canthisweak=()=>字符串代码>我想提取字符串
;我们的想法不是对所有ListofFunction和FunctionInterface进行重构。有很多。如果我必须创建一个复杂的工厂,那么我觉得这样更经济
interface FunctionInterface {
noParamsNoReturn: () => void;
noParamsNumberReturn: () => number;
propsAndNoReturn: (id: string) => void;
propsAndReturn: (id: string) => string;
}
const listOfFunctions = (): FunctionInterface => {
return {
noParamsNoReturn: () => void,
noParamsNumberReturn: () => 1,
propsAndNoReturn: (id: string) => console.log(id),
propsAndReturn: (id: string) => id,
}
}
function runThis<T>(funcName: keyof T, funcObject: T): void {
const [value, setValue] = React.useState();
// Can I have typescript set up the params here?
const theChosenFunction = ();
const theChosenFunction = (props) => {
// Can I have typescript invoke the function properly here?
const result = funcObject[funcName](); // funcObject[funcName](props)
if (result) {
setValue(result);
}
}
return {
theChosenFunction
}
}
const result = runThis<FunctionInterface>('noParamsNoReturn', listOfFunctions());
result.theChosenFunction()
// OR
result.theChosenFunction('someId');
接口函数接口{
noParamsNoReturn:()=>无效;
NoParamsUnberReturn:()=>编号;
propsAndNoReturn:(id:string)=>void;
propsAndReturn:(id:string)=>string;
}
const listOfFunctions=():FunctionInterface=>{
返回{
noParamsNoReturn:()=>无效,
NoParamsUnberReturn:()=>1,
propsAndNoReturn:(id:string)=>console.log(id),
propsAndReturn:(id:string)=>id,
}
}
函数runThis(funcName:keyof T,funcObject:T):void{
const[value,setValue]=React.useState();
//我可以让typescript在这里设置参数吗?
const theChosenFunction=();
const theChosenFunction=(道具)=>{
//我可以让typescript在这里正确调用函数吗?
const result=funcObject[funcName]();//funcObject[funcName](道具)
如果(结果){
设定值(结果);
}
}
返回{
中心功能
}
}
const result=runThis('noParamsNoReturn',listOfFunctions());
result.theChosenFunction()
//或
结果:CHOSENFunction('someId');
有内置类型和实用类型,它们分别采用函数类型T
,并使用条件类型推断来提取函数类型和返回类型:
type SomeFuncType = (x: string, y: number) => boolean;
type SomeFuncParams = Parameters<SomeFuncType>; // [x: string, y: number]
type SomeFuncRet = ReturnType<SomeFuncType>; // boolean
我给函数提供了两个通用类型参数:K
,对应于funcName
的类型,和F
,对应于funcObject
的类型。K extends PropertyKey
和F extends Recordany>
保证funcName
将是类似键的类型(string
、number
或symbol
),并且funcObject
将在该键处具有函数值属性
然后,我们可以使用chosenfunction
来允许使用可变参数列表调用函数。因此,(…props)=>funcObject[funcName](…props)
将接受任意数量的参数(包括零),并将它们传递给被调用的函数。TypeScript将此类参数列表表示为元组类型。因此,让chosenfunction
的调用签名看起来像(…props:Parameters)=>void
意味着它将接受与funcObject
键处的funcName
中的条目相同的参数,并且它不会输出任何东西(因为您的实现没有输出任何东西)
让我们看看它是否有效:
const result = runThis('noParamsNoReturn', listOfFunctions());
result.theChosenFunction(); // okay
result.theChosenFunction('someId'); // error! Expected 0 arguments, but got 1.
const anotherResult = runThis('propsAndReturn', listOfFunctions());
anotherResult.theChosenFunction(); // error! Expected 1 arguments, but got 0.
anotherResult.theChosenFunction("someId"); // okay
runThis(listOfFunctions(), 'someId'); // error! '
// FunctionInterface' is not assignable to 'string | number | symbol'.
runThis('foo', listOfFunctions()); // error!
// Property 'foo' is missing in type 'FunctionInterface'
runThis(
'bar',
{ bar: (x: string, y: number, z: boolean) => { } }
).theChosenFunction("hey", 123, true); // okay
我觉得不错
这看起来很有希望!我将在今天晚些时候详细讨论这个问题!如果道具可以是一个对象或一个值呢?props={id:string}或props=99;如果道具=99,则无法传播。你知道怎么做吗?我不明白;参数列表是一个数组,因此在(…props)=>
中,props
的类型可能是[{id:string}]
或[number]
,或者,如果有多个类似[{id:string},number]
的参数。如果你能提供你所说问题的答案,我可以看看。我明白了。你是对的。至于最小可重复性示例。这是根据我在一个私人项目上使用的代码创建的,并进行了最小程度的缩减。也许,您希望看到更多的方法示例?如果你愿意的话,我可以再举一点例子。
const result = runThis('noParamsNoReturn', listOfFunctions());
result.theChosenFunction(); // okay
result.theChosenFunction('someId'); // error! Expected 0 arguments, but got 1.
const anotherResult = runThis('propsAndReturn', listOfFunctions());
anotherResult.theChosenFunction(); // error! Expected 1 arguments, but got 0.
anotherResult.theChosenFunction("someId"); // okay
runThis(listOfFunctions(), 'someId'); // error! '
// FunctionInterface' is not assignable to 'string | number | symbol'.
runThis('foo', listOfFunctions()); // error!
// Property 'foo' is missing in type 'FunctionInterface'
runThis(
'bar',
{ bar: (x: string, y: number, z: boolean) => { } }
).theChosenFunction("hey", 123, true); // okay