react-international-phone封装组件中可选函数类型无法推断参数类型的问题
我之前也踩过TypeScript这个类型推断的小坑,正好能帮你理清问题出在哪,以及怎么解决!
问题原因
你碰到的情况其实是TypeScript对可选函数类型的保守推断逻辑导致的:
当onChange是UsePhoneInputConfig里的可选属性时,它的完整类型是((data: { phone: string }) => void) | undefined。TypeScript没法确定这个函数到底是存在的(有具体实现)还是undefined,为了避免潜在的类型错误,它会把参数data的类型推断成any。而当你把onChange设为必填时,类型就固定成了(data: { phone: string }) => void,TypeScript自然能准确推断参数类型。
具体解决办法
这里给你几个实用的方案,你可以根据自己的组件需求选:
方案1:用工具类型提取参数类型(最规范)
先从UsePhoneInputConfig里提取出onChange的参数类型,再显式给data指定类型,同时记得处理onChange可能为undefined的情况:
import { UsePhoneInputConfig } from 'react-international-phone'; // 提取onChange的参数类型,排除undefined的情况 type OnChangeParams = Parameters<NonNullable<UsePhoneInputConfig['onChange']>>[0]; const handleOnChange: UsePhoneInputConfig['onChange'] = useCallback((data: OnChangeParams) => { // 用可选链或条件判断确保onChange存在再调用 onChange?.(data.phone); }, [onChange]);
方案2:直接显式指定参数类型(最简洁)
如果确定react-international-phone传递的data结构就是{ phone: string },也可以直接给data写死类型,同时用可选链调用onChange保证运行时安全:
const handleOnChange = useCallback((data: { phone: string }) => { onChange?.(data.phone); }, [onChange]);
方案3:优化组件Props的类型定义
如果你的组件Props里包含onChange,可以直接复用UsePhoneInputConfig的类型,再结合工具类型辅助推断:
import { UsePhoneInputConfig } from 'react-international-phone'; type MyPhoneInputProps = Pick<UsePhoneInputConfig, 'onChange'>; const MyPhoneInput = ({ onChange }: MyPhoneInputProps) => { const handleOnChange = useCallback( (data: Parameters<NonNullable<MyPhoneInputProps['onChange']>>[0]) => { onChange?.(data.phone); }, [onChange] ); // 组件渲染逻辑 return <input type="tel" />; };
补充说明
你的tsconfig.json配置(虽然没贴全)其实和这个问题关联不大,核心还是TypeScript对可选函数类型的推断规则——它不会主动假设可选函数一定存在,所以会用any来兼容所有可能的情况。只要把参数类型显式指定,或者通过工具类型提取,就能解决这个问题。
备注:内容来源于stack exchange,提问作者Henok Tesfaye

