如何为被React useCallback包裹的函数启用noImplicitAny类型检查?
最优解决方案
你可以通过条件类型结合NoInfer工具类型实现兼顾三类场景的useCallback类型定义,不需要妥协规则也不会有漏判:
类型定义
import type { DependencyList } from 'react'; // TS 5.4及以上版本可以删除下面的NoInfer定义,直接使用TS内置的NoInfer type NoInfer<T> = [T][T extends any ? 0 : never]; function useCallback<T extends (...args: any[]) => any>( callback: T extends (...args: infer Args) => infer Return ? (...args: { [K in keyof Args]: NoInfer<Args[K]> }) => Return : never, deps: DependencyList ): T;
效果验证
- 未指定参数类型也无默认值的场景:正常触发
noImplicitAny报错
// 报错:Parameter 'arg' implicitly has an 'any' type. const fn = useCallback(arg => {}, []);
- 显式标注参数类型的场景:无报错,类型正常流转
// 无报错,返回的fn类型为 (arg: number) => string const fn = useCallback((arg: number) => arg.toString(), []);
- 带默认参数的场景:TS自动推断参数类型,不会触发类型报错,也不会命中
@typescript-eslint/no-inferrable-types规则
// 无报错,TS自动推断arg为number类型,返回的fn类型为 (arg?: number) => string const fn = useCallback((arg = 0) => arg.toString(), []);
原理说明
核心是通过NoInfer阻止TS从函数实现反向推断参数的隐式any类型,迫使TS要么从默认参数推导类型,要么要求用户显式标注参数类型,同时不会破坏原生的类型推导逻辑。
如果不想自己维护类型,也可以直接升级@types/react到18.2.0及以上版本,官方已经调整了useCallback的类型定义来解决这个隐式any漏报的问题,默认符合上述效果。
内容的提问来源于stack exchange,提问作者Leo Jiang
相关产品推荐
相关产品推荐

