React useEvent Hook TypeScript类型错误解决方法(禁用//@ts-ignore)
解决TypeScript中useEvent钩子的类型不兼容问题
以下React useEvent钩子的实现在JavaScript中可正常运行,但在TypeScript中报错:
import { useCallback, useLayoutEffect, useRef } from 'react'; type callbackType = (...args: any[]) => any; export const useEvent = <TF extends callbackType>(callback: TF): TF => { const functionRef = useRef<TF>(callback); useLayoutEffect(() => { functionRef.current = callback; }); return useCallback((...args) => { const functionCall = functionRef.current; return functionCall(...args); }, []); };
错误信息:TS2345: Argument of type '(...args: any[]) => any' is not assignable to parameter of type 'TF'. '(...args: any[]) => any' is assignable to the constraint of type 'TF', but 'TF' could be instantiated with a different subtype of constraint 'callbackType'.
解决方案
方案1:显式类型断言
通过as TF将返回的回调断言为泛型TF类型,明确告诉TypeScript该回调与传入的TF类型完全匹配:
import { useCallback, useLayoutEffect, useRef } from 'react'; type callbackType = (...args: any[]) => any; export const useEvent = <TF extends callbackType>(callback: TF): TF => { const functionRef = useRef<TF>(callback); useLayoutEffect(() => { functionRef.current = callback; }); return useCallback(((...args) => { const functionCall = functionRef.current; return functionCall(...args); }) as TF, []); };
方案2:更严谨的类型约束
利用TypeScript内置的Parameters和ReturnType工具类型,明确回调的参数和返回值类型,进一步缩小类型范围后再断言:
import { useCallback, useLayoutEffect, useRef } from 'react'; export const useEvent = <TF extends (...args: any[]) => any>(callback: TF): TF => { const functionRef = useRef<TF>(callback); useLayoutEffect(() => { functionRef.current = callback; }); return useCallback((...args: Parameters<TF>) => { const functionCall = functionRef.current; return functionCall(...args) as ReturnType<TF>; }, []) as TF; };
原因说明
TypeScript无法自动推断出useCallback返回的匿名回调与泛型TF的完全兼容性——虽然匿名回调符合callbackType的基础约束,但TF可能是更具体的子类型。通过显式断言或明确类型约束,我们可以消除TypeScript的类型疑虑,让代码通过类型检查。
内容的提问来源于stack exchange,提问作者Ruslan
相关产品推荐
相关产品推荐

