mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add StrictAnimatedProps to fix missing Animated types (#46659)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46659 The current `AnimatedProps` maps all types to `any` which prevents us from catching many types of issues. Introduce an alternative variant which we can adopt incrementally which enforces the underlying types. Changelog: [General][Fixed] Improved types for AnimatedProps Reviewed By: SamChou19815 Differential Revision: D63315760 fbshipit-source-id: 718fc2754cc99891e490a48d7792f626205c37e4
This commit is contained in:
committed by
Facebook GitHub Bot
parent
39c98fb8f8
commit
390925ea39
@@ -27,11 +27,24 @@ export type AnimatedProps<Props: {...}> = {
|
||||
}>)]: 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<Props: {...}> = $ReadOnly<{
|
||||
...$Exact<Props>,
|
||||
passthroughAnimatedPropExplicitValues?: ?Props,
|
||||
}>;
|
||||
|
||||
export type AnimatedComponentType<
|
||||
Props: {...},
|
||||
+Instance = mixed,
|
||||
> = React.AbstractComponent<AnimatedProps<Props>, Instance>;
|
||||
|
||||
export type StrictAnimatedComponentType<
|
||||
Props: {...},
|
||||
+Instance = mixed,
|
||||
> = React.AbstractComponent<StrictAnimatedProps<Props>, Instance>;
|
||||
|
||||
export default function createAnimatedComponent<TProps: {...}, TInstance>(
|
||||
Component: React.AbstractComponent<TProps, TInstance>,
|
||||
): AnimatedComponentType<TProps, TInstance> {
|
||||
@@ -44,40 +57,41 @@ export function unstable_createAnimatedComponentWithAllowlist<
|
||||
>(
|
||||
Component: React.AbstractComponent<TProps, TInstance>,
|
||||
allowlist: ?AnimatedPropsAllowlist,
|
||||
): AnimatedComponentType<TProps, TInstance> {
|
||||
const AnimatedComponent = React.forwardRef<AnimatedProps<TProps>, TInstance>(
|
||||
(props, forwardedRef) => {
|
||||
const [reducedProps, callbackRef] = useAnimatedProps<TProps, TInstance>(
|
||||
// $FlowFixMe[incompatible-call]
|
||||
props,
|
||||
allowlist,
|
||||
);
|
||||
const ref = useMergeRefs<TInstance>(callbackRef, forwardedRef);
|
||||
): StrictAnimatedComponentType<TProps, TInstance> {
|
||||
const AnimatedComponent = React.forwardRef<
|
||||
StrictAnimatedProps<TProps>,
|
||||
TInstance,
|
||||
>((props, forwardedRef) => {
|
||||
const [reducedProps, callbackRef] = useAnimatedProps<TProps, TInstance>(
|
||||
// $FlowFixMe[incompatible-call]
|
||||
props,
|
||||
allowlist,
|
||||
);
|
||||
const ref = useMergeRefs<TInstance>(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 (
|
||||
<Component
|
||||
{...reducedProps}
|
||||
{...passthroughAnimatedPropExplicitValues}
|
||||
style={mergedStyle}
|
||||
ref={ref}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
// NOTE: It is important that `passthroughAnimatedPropExplicitValues` is
|
||||
// spread after `reducedProps` but before `style`.
|
||||
return (
|
||||
<Component
|
||||
{...reducedProps}
|
||||
{...passthroughAnimatedPropExplicitValues}
|
||||
style={mergedStyle}
|
||||
ref={ref}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
AnimatedComponent.displayName = `Animated(${
|
||||
Component.displayName || 'Anonymous'
|
||||
|
||||
@@ -721,10 +721,18 @@ exports[`public API should not change unintentionally Libraries/Animated/createA
|
||||
>,
|
||||
}>)]: any,
|
||||
};
|
||||
export type StrictAnimatedProps<Props: { ... }> = $ReadOnly<{
|
||||
...$Exact<Props>,
|
||||
passthroughAnimatedPropExplicitValues?: ?Props,
|
||||
}>;
|
||||
export type AnimatedComponentType<
|
||||
Props: { ... },
|
||||
+Instance = mixed,
|
||||
> = React.AbstractComponent<AnimatedProps<Props>, Instance>;
|
||||
export type StrictAnimatedComponentType<
|
||||
Props: { ... },
|
||||
+Instance = mixed,
|
||||
> = React.AbstractComponent<StrictAnimatedProps<Props>, Instance>;
|
||||
declare export default function createAnimatedComponent<
|
||||
TProps: { ... },
|
||||
TInstance,
|
||||
@@ -737,7 +745,7 @@ declare export function unstable_createAnimatedComponentWithAllowlist<
|
||||
>(
|
||||
Component: React.AbstractComponent<TProps, TInstance>,
|
||||
allowlist: ?AnimatedPropsAllowlist
|
||||
): AnimatedComponentType<TProps, TInstance>;
|
||||
): StrictAnimatedComponentType<TProps, TInstance>;
|
||||
"
|
||||
`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user