javascript 如何使用正确TS属性检查编写函数 Package 器

wfauudbj  于 2023-02-21  发布在  Java
关注(0)|答案(2)|浏览(104)

基本上,对于我的用例,假设我们有这些函数

const fn1 = ({level, type}) => { console.log(level,type)}
const fn2 = ({level, username}) => { console.log(level,username)}
const fn3 = ({level, age}) => { console.log(level,age)}

现在我有两个组件调用这些函数,

const Component1 = () => { 
   const {level} = useGetUserInfo();
   useEffect((fn1({level, type: 1})) => {}, [])
}

const Component2 = () => { 
   const {level} = useGetUserInfo();
   useEffect((fn2({level, username: 'username'})) => {}, [])
   useEffect((fn3({level, age: '27'})) => {}, [])

}

因此,正如您所看到的,获取级别的部分在两个组件之间是相同的,我不希望发生这种情况(实际上,除了级别之外,还有一组从不同位置获取的公共信息,这使得代码更长,重复性更高)
因此,我想要实现的是编写一个自定义钩子,它接受fn数组并返回 Package 器fn
所以我才能这样写

const Component1 = () => { 
   const [returnFn1] = useWrapperFn(fn1);
   useEffect((returnFn1({type: 1})) => {}, []). // --> here i dont need to pass level anymore
}

const Component2 = () => { 
   const [returnFn2, returnFn3] = useWrapperFn(fn2,fn3);
   useEffect((returnFn2({username: 'username'})) => {}, []) // --> no need to pass in level
   useEffect((returnFn3({age: '27'})) => {}, []) // --> no need to pass in level
}

到目前为止,这是我钩子**,它感谢您的帮助,为修复提供反馈**:

const useWrapperFn = <T extends any[]>(fns: ((...args: T) => void)[]) => {
   const {level} = useGetUserInfo();

  const returnFns = fns.map((fn) => {
    return ((...args: any[]) => {
      // @ts-ignore
      fn({ ...args[0], level}); //-> here i inject the level
    }) as (props: Omit<NonNullable<Parameters<typeof fn>[0]>, 'level'>) => void;
  });

  return returnFns;
};

export default useWrapperFn;

我想要的是,当我使用returnFn时,**它应该仍然对其余字段进行正确的 prop 类型检查。**例如,当我调用returnFn1而没有传入type时,将提示TS错误。

returnFn1({type: 1}) // -> works 
returnFn1() // -> will throw ts error missing type
    • 当前行为**

目前JS明智,逻辑正确
对于TS lint检查,它使用组件1(仅向数组传递1个fn)
然而,对于Component2(传递多于1个fn),则TS lint将是所有函数属性的组合
这就意味着

returnFn2({username: 'username'}) // --> currently prompt that missing `age` , wherease `age` belong to fn3

returnFn3({age: '27'}) // --> currently prompt that missing `usernamse` , wherease `username` belong to fn2

那么,是否有必要修改我的useWrapperFn钩子,以便它返回的returnedFn数组具有正确的props类型

pgky5nke

pgky5nke1#

要修复useWrapperFn钩子的问题,可以使用TypeScript的实用程序类型,如Parameters和Omit。

const useWrapperFn = <T extends any[]>(fns: ((...args: T) => void)[]) => 
{
  const { level } = useGetUserInfo();

  const returnFns = fns.map((fn) => {
   return ((...args: T) => {
    const [fnArgs] = args;
    fn({ ...fnArgs, level });
  }) as (props: Omit<NonNullable<Parameters<typeof fn>[0]>, 'level'>) => void;
});

return returnFns;
};

export default useWrapperFn;
yquaqz18

yquaqz182#

这就是你所需要的一个强有力的类型声明:

const useWrapperFn = <T extends ((...args: any[]) => any)[]>(fns: [...T]): {
  [K in keyof T]: (props: Omit<NonNullable<Parameters<T[K]>[0]>, 'level'>) => void
} => {
  const { level } = useGetUserInfo();

  const returnFns = fns.map((fn) => {
    return ((...args: any[]) => {
      // @ts-ignore
      fn({ ...args[0], level }); //-> here i inject the level
    })
  });

  return returnFns as any;
};

演示:www.example.comhttps://www.typescriptlang.org/play?ssl=15&ssc=1&pln=1&pc=1#code/MYewdgzgLgBArhApgdQE4EMAOnGoGJgwC8MAPACoyIAeUiYAJhDABQsB0n6qA5hAFwx0YAJ4BtALoBKYgD4hoqZNksAZpEFjO7ctMEBvAFAwYYgNIwAloQDWiESFUxdglplQhMAmAHkAtpZQpABy4MFwADYR6ABGEYikAArc6H6IdKgQFOYSsmIADLkANDAA5PEAbogRpbIyRPIVIJYMhgC+cjBGJqCQsPowldUwHSQDQxGCAIwjhsYwvdAwqOlwqGAEzCTqEOx+WGzq9fLdJsur66wcXLzewuLSnadnMAD0rzAAAlAQALSWPDAIBW8xe6hYA203D4BQkJQmIykAG43q9fvIABa4RBWKxgABWiGAsCgWMGiCqEVBiPmbWRcxMKyga0ITJZmyEzHuSPaPMMi1gK2I8CQaCwOHwYBYYhYniglnABhgFTgiEEYDgfhiuERnXyJVlmHliq6MAgcAYIHVmu1qF1DRgU2khhWsIh8xVapg+XaUhdiDETvdJnNlsEPrp-rdp1DVu9vqAA

相关问题