From 1dc6c86df827a44a8c0ac4cc7f239b2507ecd33d Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Wed, 8 Jan 2025 00:47:10 -0300 Subject: [PATCH] fix(fuselage-hooks): Stricter generics for `useEffectEvent` (#1521) --- .changeset/eight-birds-invite.md | 6 ++++++ packages/fuselage-hooks/src/useEffectEvent.ts | 9 ++++++--- .../src/components/PaginatedSelect/PaginatedSelect.tsx | 6 +++--- packages/fuselage/src/components/Select/SelectLegacy.tsx | 8 ++++---- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 .changeset/eight-birds-invite.md diff --git a/.changeset/eight-birds-invite.md b/.changeset/eight-birds-invite.md new file mode 100644 index 0000000000..7e3351cd3e --- /dev/null +++ b/.changeset/eight-birds-invite.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/fuselage-hooks': patch +'@rocket.chat/fuselage': patch +--- + +fix(fuselage-hooks): Stricter generics for `useEffectEvent` diff --git a/packages/fuselage-hooks/src/useEffectEvent.ts b/packages/fuselage-hooks/src/useEffectEvent.ts index bbe9f8a1b9..5d3c106a03 100644 --- a/packages/fuselage-hooks/src/useEffectEvent.ts +++ b/packages/fuselage-hooks/src/useEffectEvent.ts @@ -13,10 +13,13 @@ import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'; * @returns a stable callback * @public */ -export const useEffectEvent =

( - fn: (...args: P) => T, -): ((...args: P) => T) => { +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +export const useEffectEvent = (fn: TFunction) => { const fnRef = useRef(fn); + + type P = TFunction extends (...args: infer P) => any ? P : never; + type T = TFunction extends (...args: any) => infer T ? T : never; + const stableFnRef = useRef( (...args: P): T => fnRef.current.call(undefined, ...args), ); diff --git a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx b/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx index c2cf23286a..f9bfb9b56d 100644 --- a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx +++ b/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx @@ -1,7 +1,7 @@ import { useEffectEvent, useResizeObserver } from '@rocket.chat/fuselage-hooks'; import { type ElementType, useState, useRef, useMemo } from 'react'; -import { type SelectProps } from '..'; +import type { OptionType, SelectOption, SelectProps } from '..'; import { prevent } from '../../helpers/prevent'; import AnimatedVisibility from '../AnimatedVisibility'; import Box from '../Box'; @@ -52,9 +52,9 @@ export const PaginatedSelect = ({ const [visible, hide, show] = useVisible(); - const internalChangedByClick = useEffectEvent(([value]) => { + const internalChangedByClick = useEffectEvent(([value]: OptionType) => { setInternalValue(value); - onChange(value); + onChange(value as SelectOption[0]); // FIXME hide(); }); diff --git a/packages/fuselage/src/components/Select/SelectLegacy.tsx b/packages/fuselage/src/components/Select/SelectLegacy.tsx index 2f1e8b3c92..26ba243378 100644 --- a/packages/fuselage/src/components/Select/SelectLegacy.tsx +++ b/packages/fuselage/src/components/Select/SelectLegacy.tsx @@ -89,9 +89,9 @@ export const SelectLegacy = forwardRef( ) => { const [internalValue, setInternalValue] = useState(value || ''); - const internalChangedByKeyboard = useEffectEvent(([value]) => { + const internalChangedByKeyboard = useEffectEvent(([value]: OptionType) => { setInternalValue(value); - onChange(value); + onChange(value as SelectOption[0]); // FIXME }); const option = options.find( @@ -123,9 +123,9 @@ export const SelectLegacy = forwardRef( const removeFocusClass = () => innerRef.current?.classList.remove('focus-visible'); - const internalChangedByClick = useEffectEvent(([value]) => { + const internalChangedByClick = useEffectEvent(([value]: OptionType) => { setInternalValue(value); - onChange(value); + onChange(value as SelectOption[0]); // FIXME removeFocusClass(); hide(); });