我正在创建一个名为useUpdate
的钩子,在声明类型时遇到问题,代码如下所示
type CallBack<T extends readonly any[]> = (
...args: T
) => void | (() => void | undefined);
function useUpdate<T extends readonly any[]>(
callback: CallBack<T>,
deps: T
) {
const didMount = useRef(false);
const prevDeps = useRef(deps);
useEffect(() => {
if (!didMount.current) {
didMount.current = true;
return;
}
const clean = callback(...prevDeps.current);
prevDeps.current = deps;
return () => {
if (clean) {
clean();
}
};
}, deps);
}
使用它时,如果回调包含args,则没有问题,但如果没有为回调提供args,则DEP的类型将不正确
const state: boolean = useSomethingElse(); // get changable data from anywere else
// OK, no type error
useUpdate((prevState) => {
console.log('I want to compare the current state and prevState', prevState, state);
},[state]);
useUpdate(() => {
console.log('I only care about the current state', state);
},[state]); // Type error occurs on this line, the message is:
// Argument of type '[boolean]' is not assignable to parameter of type '[]'.
// Source has 1 element(s) but target allows only 0.ts(2345)
我知道这是因为TypeScript将T设置为回调参数,如果没有提供参数,则为[],但是有没有办法让TypeScript在设置T时使用DEP类型并跳过回调参数的类型?