From 1d3dddac984c3a7870ff1ac3eebcb6a78e303269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 5 Nov 2025 15:23:56 +0800 Subject: [PATCH 1/2] chore: useEvent type support undefined --- src/hooks/useEvent.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/hooks/useEvent.ts b/src/hooks/useEvent.ts index f9bb7dce..1a821eff 100644 --- a/src/hooks/useEvent.ts +++ b/src/hooks/useEvent.ts @@ -2,12 +2,14 @@ /* eslint-disable react-hooks/exhaustive-deps */ import * as React from 'react'; -function useEvent(callback: T): T { - const fnRef = React.useRef(); +function useEvent any>( + callback: T | undefined, +): T { + const fnRef = React.useRef(callback); fnRef.current = callback; - const memoFn = React.useCallback( - ((...args: any) => fnRef.current?.(...args)) as any, + const memoFn = React.useCallback( + ((...args) => fnRef.current?.(...args)) as T, [], ); From 7eb618d78aa1c4604d891ce93bf6bf125c0b1d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 5 Nov 2025 15:43:04 +0800 Subject: [PATCH 2/2] chore: update --- src/hooks/useEvent.ts | 12 ++++++++---- tests/hooks.test.tsx | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/hooks/useEvent.ts b/src/hooks/useEvent.ts index 1a821eff..4c6f92a0 100644 --- a/src/hooks/useEvent.ts +++ b/src/hooks/useEvent.ts @@ -2,14 +2,18 @@ /* eslint-disable react-hooks/exhaustive-deps */ import * as React from 'react'; -function useEvent any>( - callback: T | undefined, -): T { +function useEvent any) | undefined>( + callback: T, +): undefined extends T + ? ( + ...args: Parameters> + ) => ReturnType> | undefined + : T { const fnRef = React.useRef(callback); fnRef.current = callback; const memoFn = React.useCallback( - ((...args) => fnRef.current?.(...args)) as T, + (...args: any[]) => fnRef.current?.(...args), [], ); diff --git a/tests/hooks.test.tsx b/tests/hooks.test.tsx index b8154c66..fc096500 100644 --- a/tests/hooks.test.tsx +++ b/tests/hooks.test.tsx @@ -9,6 +9,7 @@ import useMobile from '../src/hooks/useMobile'; import useState from '../src/hooks/useState'; import useSyncState from '../src/hooks/useSyncState'; import useControlledState from '../src/hooks/useControlledState'; +import useEvent from '../src/hooks/useEvent'; global.disableUseId = false; @@ -706,4 +707,23 @@ describe('hooks', () => { expect(container.textContent).toEqual('2'); }); }); + + describe('useEvent', () => { + it('extract type', () => { + const Demo = (props: { + canUndefined?: (a: number) => boolean; + notUndefined: (a: number) => boolean; + }) => { + const ua = useEvent(props.canUndefined); + const ub = useEvent(props.notUndefined); + + ua(1); + ub(2); + + return null; + }; + + expect(Demo).toBeTruthy(); + }); + }); });