使用TypeScript的Framer-motion动画:scrollY无法找到.current属性
解决useScroll钩子scrollY属性的类型定义问题
首先根据你的代码逻辑,明确scrollY的结构:它包含数值类型的current、prev属性,以及用于监听滚动变化的onChange方法。我们先定义对应的类型:
interface ScrollYState { current: number; prev: number; onChange: (callback: () => void) => () => void; }
接下来根据useScroll的来源(自定义/第三方库),选择对应的类型处理方式:
方式一:为自定义useScroll钩子添加返回类型
如果useScroll是你自己实现的钩子,直接给它指定返回类型即可:
const useScroll = (): { scrollY: ScrollYState } => { // 这里是你的useScroll钩子实现逻辑 };
方式二:处理第三方库的useScroll类型缺失问题
如果是使用第三方库(比如react-use)的useScroll但类型不匹配,有两种快速解决方式:
类型断言(快速临时方案)
在解构时直接断言scrollY的类型:
const { scrollY } = useScroll() as { scrollY: ScrollYState };
模块扩展(优雅持久方案)
创建types/[库名].d.ts文件(比如types/react-use.d.ts),扩展原有模块的类型:
import 'react-use'; declare module 'react-use' { export function useScroll(): { scrollY: ScrollYState; // 可添加其他需要的属性,比如scrollX }; }
完整类型化后的业务代码
import { useState, useEffect } from 'react'; interface ScrollYState { current: number; prev: number; onChange: (callback: () => void) => () => void; } // 自定义useScroll示例(如果用第三方库可忽略这段) const useScroll = (): { scrollY: ScrollYState } => { const [scrollState, setScrollState] = useState<ScrollYState>({ current: 0, prev: 0, onChange: () => () => {}, }); useEffect(() => { const updateScroll = () => { setScrollState(prev => ({ ...prev, prev: prev.current, current: window.scrollY, })); }; window.addEventListener('scroll', updateScroll); const onChange = (callback: () => void) => { window.addEventListener('scroll', callback); return () => window.removeEventListener('scroll', callback); }; return () => window.removeEventListener('scroll', updateScroll); }, []); return { scrollY: { ...scrollState, onChange } }; }; // 菜单组件代码 const ScrollMenu = () => { const { scrollY } = useScroll(); const [isScrolling, setScrolling] = useState<boolean>(false); const handleScroll = () => { // 类型明确后可去掉可选链,让TypeScript做严格检查 if (scrollY.current < scrollY.prev) setScrolling(false); if (scrollY.current > 100 && scrollY.current > scrollY.prev) setScrolling(true); }; useEffect(() => { return scrollY.onChange(handleScroll); }, [scrollY]); return ( <div className={`menu ${isScrolling ? 'hidden' : 'visible'}`}> {/* 菜单内容 */} </div> ); };
注意事项
- 优先查看第三方库的官方文档,确认是否有现成的类型定义包(比如
@types/[库名]) - 类型定义要和
scrollY的实际运行时结构完全匹配,避免类型不兼容报错
内容的提问来源于stack exchange,提问作者Adrián Pérez García
相关产品推荐
相关产品推荐

