diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index 72fd367049b..fc9153f27cb 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -27,11 +27,24 @@ export type AnimatedProps = { }>)]: any, }; +// We could use a mapped type here to introduce acceptable Animated variants +// of properties, instead of doing so in the core StyleSheetTypes +// Inexact Props are not supported, they'll be made exact here. +export type StrictAnimatedProps = $ReadOnly<{ + ...$Exact, + passthroughAnimatedPropExplicitValues?: ?Props, +}>; + export type AnimatedComponentType< Props: {...}, +Instance = mixed, > = React.AbstractComponent, Instance>; +export type StrictAnimatedComponentType< + Props: {...}, + +Instance = mixed, +> = React.AbstractComponent, Instance>; + export default function createAnimatedComponent( Component: React.AbstractComponent, ): AnimatedComponentType { @@ -44,40 +57,41 @@ export function unstable_createAnimatedComponentWithAllowlist< >( Component: React.AbstractComponent, allowlist: ?AnimatedPropsAllowlist, -): AnimatedComponentType { - const AnimatedComponent = React.forwardRef, TInstance>( - (props, forwardedRef) => { - const [reducedProps, callbackRef] = useAnimatedProps( - // $FlowFixMe[incompatible-call] - props, - allowlist, - ); - const ref = useMergeRefs(callbackRef, forwardedRef); +): StrictAnimatedComponentType { + const AnimatedComponent = React.forwardRef< + StrictAnimatedProps, + TInstance, + >((props, forwardedRef) => { + const [reducedProps, callbackRef] = useAnimatedProps( + // $FlowFixMe[incompatible-call] + props, + allowlist, + ); + const ref = useMergeRefs(callbackRef, forwardedRef); - // Some components require explicit passthrough values for animation - // to work properly. For example, if an animated component is - // transformed and Pressable, onPress will not work after transform - // without these passthrough values. - // $FlowFixMe[prop-missing] - const {passthroughAnimatedPropExplicitValues, style} = reducedProps; - const passthroughStyle = passthroughAnimatedPropExplicitValues?.style; - const mergedStyle = useMemo( - () => composeStyles(style, passthroughStyle), - [passthroughStyle, style], - ); + // Some components require explicit passthrough values for animation + // to work properly. For example, if an animated component is + // transformed and Pressable, onPress will not work after transform + // without these passthrough values. + // $FlowFixMe[prop-missing] + const {passthroughAnimatedPropExplicitValues, style} = reducedProps; + const passthroughStyle = passthroughAnimatedPropExplicitValues?.style; + const mergedStyle = useMemo( + () => composeStyles(style, passthroughStyle), + [passthroughStyle, style], + ); - // NOTE: It is important that `passthroughAnimatedPropExplicitValues` is - // spread after `reducedProps` but before `style`. - return ( - - ); - }, - ); + // NOTE: It is important that `passthroughAnimatedPropExplicitValues` is + // spread after `reducedProps` but before `style`. + return ( + + ); + }); AnimatedComponent.displayName = `Animated(${ Component.displayName || 'Anonymous' diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 99ad037dc3b..554b0a19eea 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -721,10 +721,18 @@ exports[`public API should not change unintentionally Libraries/Animated/createA >, }>)]: any, }; +export type StrictAnimatedProps = $ReadOnly<{ + ...$Exact, + passthroughAnimatedPropExplicitValues?: ?Props, +}>; export type AnimatedComponentType< Props: { ... }, +Instance = mixed, > = React.AbstractComponent, Instance>; +export type StrictAnimatedComponentType< + Props: { ... }, + +Instance = mixed, +> = React.AbstractComponent, Instance>; declare export default function createAnimatedComponent< TProps: { ... }, TInstance, @@ -737,7 +745,7 @@ declare export function unstable_createAnimatedComponentWithAllowlist< >( Component: React.AbstractComponent, allowlist: ?AnimatedPropsAllowlist -): AnimatedComponentType; +): StrictAnimatedComponentType; " `;