React-native-reanimated: TypeScript - Issue with transform (and other) props (1.8.0)

Created on 8 Apr 2020  路  38Comments  路  Source: software-mansion/react-native-reanimated

Hello.

I've just upgraded from 1.4.0 and I keep getting lots of TypeScript compilation errors. So for example following code:

export type AnimatedNumber = Animated.Adaptable<number>; // or Animated.Value<number>

export type AnimatedPosition = {
  x: AnimatedNumber;
  y: AnimatedNumber;
};

type Props = {
  initialPosition: AnimatedPosition;
};

const GameInteractableFlag = ({initialPosition}: Props) => {
  return (
    <Animated.View
      style={[
        styles.imageFlag,
        {
          transform: [ // these lines
            {translateX: initialPosition.x}, // and this
            {translateY: initialPosition.y}, // and this
          ], // and this
        },
      ]}>
      <FastImage source={images.flag} imageStyle={styles.imageFlag} />
    </Animated.View>
  );
};

is showing following error:

No overload matches this call.
  Overload 1 of 2, '(props: Readonly<AnimateProps<ViewStyle, ViewProps>>): View', gave the following error.
    Type '{ transform: ({ translateX: Animated.Adaptable<number>; } | { translateY: Animated.Adaptable<number>; })[]; }' is not assignable to type 'false | AnimateStyle<ViewStyle> | RegisteredStyle<AnimateStyle<ViewStyle>> | RecursiveArray<false | AnimateStyle<ViewStyle> | RegisteredStyle<...> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Types of property 'transform' are incompatible.
        Type '({ translateX: Adaptable<number>; } | { translateY: Adaptable<number>; })[]' is not assignable to type 'AnimatedTransform'.
          Type '{ translateX: Adaptable<number>; } | { translateY: Adaptable<number>; }' is not assignable to type 'never'.
            Type '{ translateX: Animated.Adaptable<number>; }' is not assignable to type 'never'.
  Overload 2 of 2, '(props: AnimateProps<ViewStyle, ViewProps>, context?: any): View', gave the following error.
    Type '{ transform: ({ translateX: Animated.Adaptable<number>; } | { translateY: Animated.Adaptable<number>; })[]; }' is not assignable to type 'false | AnimateStyle<ViewStyle> | RegisteredStyle<AnimateStyle<ViewStyle>> | RecursiveArray<false | AnimateStyle<ViewStyle> | RegisteredStyle<...> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Types of property 'transform' are incompatible.
        Type '({ translateX: Adaptable<number>; } | { translateY: Adaptable<number>; })[]' is not assignable to type 'AnimatedTransform'.
          Type '{ translateX: Adaptable<number>; } | { translateY: Adaptable<number>; }' is not assignable to type 'never'.
            Type '{ translateX: Animated.Adaptable<number>; }' is not assignable to type 'never'.ts(2769)

and also for example animated SVG path:

import {Path} from 'react-native-svg';
const AnimatedPath = Animated.createAnimatedComponent<typeof Path>(Path);

...

<AnimatedPath
      d={d}
      strokeDasharray={length}
      strokeDashoffset={interpolate(runner, { // these lines below
        inputRange: [0, 1],
        outputRange: [length, 1],
        extrapolate: Extrapolate.CLAMP,
      })}
      opacity={interpolate(runner, {.  // and these lines below
        inputRange: [0, 0.25, 1],
        outputRange: [0, 0.8, 1],
        extrapolate: Extrapolate.CLAMP,
      })}
      fill={fill}
      stroke={stroke}
      strokeWidth={strokeWidth}
    />

are showing following error message:

Type 'AnimatedNode<number>' is not assignable to type 'string | number | undefined'.
  Type 'AnimatedNode<number>' is not assignable to type 'number'.ts(2322)
index.d.ts(136, 3): The expected type comes from property 'strokeDashoffset' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<PathProps, any, any>> & Readonly<PathProps> & Readonly<...>'

Can anyone help me to make this work? Thank you so much!

Most helpful comment

Able to reproduce, issue appears in strict mode

All 38 comments

I copy pasted your snippet for GameInteractableFlag and it works fine for me on 1.7.1 with patch #707, so that is a bit odd..

@Jomik hello and thanks! Could you please try this example with 1.8.0 to see if it works for you even there?

Works fine on 1.8.0 as well for me.
I do not have styles.flag, so I replaced that with {}, and FastImage with View. Neither should cause an issue though, as we are using ViewStyle and not inferring anything, but I want to mention it.
My initial thought is that it is hitting the else condition of https://github.com/software-mansion/react-native-reanimated/pull/707/files#diff-c3ef4cab7a703f83e079356d6873fef5R150
But...

<Animated.View
      style={{
        transform: [
          {translateX: initialPosition.x},
          {translateY: initialPosition.y},
        ],
      }}>
      <FastImage source={images.flag} imageStyle={styles.imageFlag} />
    </Animated.View>

Even this is still throwing following compilation error:

No overload matches this call.
  Overload 1 of 2, '(props: Readonly<AnimateProps<ViewStyle, ViewProps>>): View', gave the following error.
    Type '{ transform: ({ translateX: AnimatedNumber; } | { translateY: AnimatedNumber; })[]; }' is not assignable to type 'StyleProp<AnimateStyle<ViewStyle>>'.
      Types of property 'transform' are incompatible.
        Type '({ translateX: AnimatedNumber; } | { translateY: AnimatedNumber; })[]' is not assignable to type 'AnimatedTransform'.
          Type '{ translateX: AnimatedNumber; } | { translateY: AnimatedNumber; }' is not assignable to type 'never'.
            Type '{ translateX: AnimatedNumber; }' is not assignable to type 'never'.
  Overload 2 of 2, '(props: AnimateProps<ViewStyle, ViewProps>, context?: any): View', gave the following error.
    Type '{ transform: ({ translateX: AnimatedNumber; } | { translateY: AnimatedNumber; })[]; }' is not assignable to type 'StyleProp<AnimateStyle<ViewStyle>>'.
      Types of property 'transform' are incompatible.
        Type '({ translateX: AnimatedNumber; } | { translateY: AnimatedNumber; })[]' is not assignable to type 'AnimatedTransform'.
          Type '{ translateX: AnimatedNumber; } | { translateY: AnimatedNumber; }' is not assignable to type 'never'.
            Type '{ translateX: AnimatedNumber; }' is not assignable to type 'never'.ts(2769)
index.d.ts(2361, 5): The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<View> & Readonly<AnimateProps<ViewStyle, ViewProps>> & Readonly<...>'
index.d.ts(2361, 5): The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<View> & Readonly<AnimateProps<ViewStyle, ViewProps>> & Readonly<...>'

Btw I got 150+ errors like this from TS compilation across whole project after 1.8.0 upgrade :(

cc @hastom

Another example could be:

import Animated from 'react-native-reanimated';
import {Svg, Line} from 'react-native-svg';
...
const ALine = Animated.createAnimatedComponent(Line);

...

<ALine
        x1={x1} // is type of Animated.Value<number>
        y1={y1} // is type of Animated.Value<number>
        x2={x2} // is type of Animated.Value<number>
        y2={y2} // is type of Animated.Value<number>
        stroke={colors.background}
        strokeDasharray={[2, 7]}
        strokeOpacity="0.5"
        strokeWidth="2"
      />

with compilation error message:

Type 'AnimatedNumber' is not assignable to type 'string | number | undefined'.
  Type 'AnimatedValue<number>' is not assignable to type 'number'.

143         x1={x1}
            ~~

btw my lib versions looks like this:

react-native: 0.62.1
react-native-reanimated: 1.8.0
typescript: 3.8.3
@types/react: 16.9.11
@types/react-native: 0.62.1

Oh.
Can you try with @types/react-native ^0.60.22
That's what I use, I'm using expo..
Just curious if there was a change to ViewStyle..

Didn鈥檛 work using 0.60.22 @types/react-native

also experiencing type errors with transform

I鈥檒l check tomorrow morning, maybe it鈥檚 typescript version

Able to reproduce, issue appears in strict mode

@hastom nice, thanks!

@jakub-gonet @kmagiera do you think its possible to create minor release with this typescript definition fix?

@sebinq can you confirm your code is working with this patch?

Actually, it is still not working :(

PR above fixes issue with transform style. Issue with createAnimatedComponent is caused by #696 May be it should be reverted or we can copy type from "@types/react-native": "~0.62.2" as it introduces typed version of createAnimatedComponent as well?

Yep, I can confirm that some of my compiler errors are gone. I missed that because there is just so many of them.

@sebinq can you post here rest of the errors and example code which is causing that? I wonder if we also need to add null | undefined to that change with generics in createAnimatedComponent

const AnimatedImage = Animated.createAnimatedComponent(Image);

 <AnimatedImage
      source={source}
      style={[
        styles.avatar,
        {
          opacity: mix(progress, 0, 1),
          transform: [{translateX: x}, {translateY: y}, {scale}],
        },
      ]}
    />

and error:

No overload matches this call.
  Overload 1 of 2, '(props: Readonly<ImageProps>): Image', gave the following error.
    Type '{ opacity: Animated.Node<number>; transform: ({ translateX: number; } | { translateY: number; } | { scale: Animated.Node<number>; })[]; }' is not assignable to type 'false | ImageStyle | RegisteredStyle<ImageStyle> | RecursiveArray<false | ImageStyle | RegisteredStyle<ImageStyle> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Types of property 'opacity' are incompatible.
        Type 'AnimatedNode<number>' is not assignable to type 'number'.
  Overload 2 of 2, '(props: ImageProps, context?: any): Image', gave the following error.
    Type '{ opacity: Animated.Node<number>; transform: ({ translateX: number; } | { translateY: number; } | { scale: Animated.Node<number>; })[]; }' is not assignable to type 'false | ImageStyle | RegisteredStyle<ImageStyle> | RecursiveArray<false | ImageStyle | RegisteredStyle<ImageStyle> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Types of property 'opacity' are incompatible.
        Type 'AnimatedNode<number>' is not assignable to type 'number'.ts(2769)

Btw mix is bInterpolate from react-native-redash

Its already all of them in meanings of component uniqueness.. Animated Image, Animated SVG path and animated views. These are all across of my project.

@jakub-gonet issue with createAnimatedComponent is that now it returns same component type as it gets. And initially components does not accept Animated values as properties. It's not about checks it's just wrong to return same type

723 + #722 should work

@jakub-gonet Can we make a minor release from these typing changes?

I need to prepare some simple test to test those changes before merging, especially for types copied from RN.

If everything will be working alright I'm happy to release it - I just don't want to make fix release fixing the fix release :smile:

Ok, thanks for info :)

BTW, do those two PRs fix your issue with TS?

It is working for most cases but there are new places where types are broken :D

No overload matches this call.
  Overload 1 of 2, '(props: Readonly<AnimateProps<ImageStyle, ImageProps>>): Image', gave the following error.
    Type '{ transform: AnimatedTransform[]; }' is not assignable to type 'false | AnimateStyle<ImageStyle> | RegisteredStyle<AnimateStyle<ImageStyle>> | RecursiveArray<false | AnimateStyle<ImageStyle> | RegisteredStyle<...> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Types of property 'transform' are incompatible.
        Type 'AnimatedTransform[]' is not assignable to type 'AnimatedTransform'.
          Type 'AnimatedTransform' is not assignable to type 'AdaptTransforms<PerpectiveTransform> | AdaptTransforms<RotateTransform> | AdaptTransforms<RotateXTransform> | ... 8 more ... | AdaptTransforms<...>'.
            Property 'skewY' is missing in type 'AnimatedTransform' but required in type 'AdaptTransforms<SkewYTransform>'.
  Overload 2 of 2, '(props: AnimateProps<ImageStyle, ImageProps>, context?: any): Image', gave the following error.
    Type '{ transform: AnimatedTransform[]; }' is not assignable to type 'false | AnimateStyle<ImageStyle> | RegisteredStyle<AnimateStyle<ImageStyle>> | RecursiveArray<false | AnimateStyle<ImageStyle> | RegisteredStyle<...> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Types of property 'transform' are incompatible.
        Type 'AnimatedTransform[]' is not assignable to type 'AnimatedTransform'.ts(2769)
index.d.ts(720, 5): 'skewY' is declared here.

Or Animated Flatlist:

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

...

<AnimatedFlatList
        ref={listRef}
        data={data}
        horizontal  // error here
        keyExtractor={keyExtractor}
        renderItem={renderItem}  // and here
        style={containerStyle}  // and here too
        onScroll={onScrollEvent({x: sliderX})}
        scrollEventThrottle={16}
        snapToInterval={itemWidthWithSpacing || itemWidth}
        showsHorizontalScrollIndicator={false}
        getItemLayout={getItemLayout}
        disableIntervalMomentum
        disallowInterruption
        waitFor={waitFor}
        simultaneousHandlers={simultaneousHandlers}
        {...otherScrollProps}
      />
Type 'boolean | null' is not assignable to type 'WithAnimatedValue<boolean | null | undefined> | undefined'.
  Type 'null' is not assignable to type 'WithAnimatedValue<boolean | null | undefined> | undefined'.ts(2322)
index.d.ts(3979, 5): The expected type comes from property 'horizontal' which is declared here on type 'IntrinsicAttributes & AnimatedProps<NativeViewGestureHandlerProperties & FlatListProperties<unknown>> & { ...; }'

Type 'ListRenderItem<any> | null | undefined' is not assignable to type 'WithAnimatedValue<ListRenderItem<unknown> | null | undefined>'.
  Type 'undefined' is not assignable to type 'WithAnimatedValue<ListRenderItem<unknown> | null | undefined>'.ts(2322)
index.d.ts(4051, 5): The expected type comes from property 'renderItem' which is declared here on type 'IntrinsicAttributes & AnimatedProps<NativeViewGestureHandlerProperties & FlatListProperties<unknown>> & { ...; }'

ype 'false | object | ViewStyle | RegisteredStyle<ViewStyle> | RecursiveArray<false | ViewStyle | RegisteredStyle<ViewStyle> | null | undefined> | object[] | null | undefined' is not assignable to type 'WithAnimatedValue<StyleProp<ViewStyle>> | undefined'.
  Type 'null' is not assignable to type 'WithAnimatedValue<StyleProp<ViewStyle>> | undefined'.ts(2322)
index.d.ts(6444, 5): The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & AnimatedProps<NativeViewGestureHandlerProperties & FlatListProperties<unknown>> & { ...; }'

Same issue here

@sebinq, @geroale does change from #722 and reverted change from #696 fixes your issues with tsc? If yes I think we can merge first and revert second and then release 1.9, so people won't have broken types for a long time, then I would test if #723 actually works.

@jakub-gonet Unfortunately, I'm out of office until end of this month so I can't help here :( But maybe I'll try to reproduce these issues at home.

the patches do not seem to fix all of the errors in my project:

src/components/ColorPicker/Wheel.tsx:101:39 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(props: Readonly<AnimateProps<ViewStyle, ViewProps>>): View', gave the following error.
    Type '{ opacity: Animated.Node<number>; transform: { rotate: Animated.Node<number>; }[]; }' is not assignable to type 'false | AnimateStyle<ViewStyle> | RegisteredStyle<AnimateStyle<ViewStyle>> | RecursiveArray<false | AnimateStyle<ViewStyle> | RegisteredStyle<...> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Type '{ opacity: Animated.Node<number>; transform: { rotate: Animated.Node<number>; }[]; }' is not assignable to type 'AnimateStyle<ViewStyle>'.
        Types of property 'transform' are incompatible.
          Type '{ rotate: AnimatedNode<number>; }[]' is not assignable to type 'AnimatedTransform'.
            Type '{ rotate: Animated.Node<number>; }' is not assignable to type 'AdaptTransforms<PerpectiveTransform> | AdaptTransforms<RotateTransform> | AdaptTransforms<RotateXTransform> | ... 8 more ... | AdaptTransforms<...>'.
              Type '{ rotate: Animated.Node<number>; }' is not assignable to type 'AdaptTransforms<RotateTransform>'.
                Types of property 'rotate' are incompatible.
                  Type 'AnimatedNode<number>' is not assignable to type 'Adaptable<string>'.
                    Type 'AnimatedNode<number>' is not assignable to type 'AnimatedNode<string>'.
  Overload 2 of 2, '(props: AnimateProps<ViewStyle, ViewProps>, context?: any): View', gave the following error.
    Type '{ opacity: Animated.Node<number>; transform: { rotate: Animated.Node<number>; }[]; }' is not assignable to type 'false | AnimateStyle<ViewStyle> | RegisteredStyle<AnimateStyle<ViewStyle>> | RecursiveArray<false | AnimateStyle<ViewStyle> | RegisteredStyle<...> | null | undefined> | readonly (false | ... 3 more ... | undefined)[] | null | undefined'.
      Type '{ opacity: Animated.Node<number>; transform: { rotate: Animated.Node<number>; }[]; }' is not assignable to type 'AnimateStyle<ViewStyle>'.

101             style={[styles.container, animatedStyle]}

all remaining errors are related to rotation transforms

Not using TypeScript, but I'm also seeing odd transform issues as well just going from 1.7.1 -> 1.8.0. Rolling back to 1.7.1 fixes my issue.

Specifically the calculations for translateX and scale values are slightly off. For some reason though the translateY value is not off. Here's a snippet of the calculations and how they're used. Note: the issue occurs even on initial render, before any handlers are fired.

```js
const dragX = useRef(new Value(0)).current
const dragY = useRef(new Value(0)).current
const offsetX = useRef(new Value(0)).current
const offsetY = useRef(new Value(0)).current
const panState = useRef(new Value(-1)).current
const pinchScale = useRef(new Value(1)).current
const baseScale = useRef(new Value(1)).current

const translateX = cond(
eq(panState, State.ACTIVE),
add(offsetX, dragX),
set(offsetX, add(offsetX, dragX))
)

const translateY = cond(
eq(panState, State.ACTIVE),
add(offsetY, dragY),
set(offsetY, add(offsetY, dragY))
)

const scale = diffClamp(multiply(baseScale, pinchScale), 0.5, 3)

return (
{/* container elements /}
onGestureEvent={onPinchGesture}
onHandlerStateChange={onPinchHandlerState}
>
style={[
styles.zoomView,
{
transform: [{ scale }]
}
]}
>
maxPointers={1}
onGestureEvent={onPan}
onHandlerStateChange={onPan}
>
style={[
styles.panView,
{
transform: [{ translateX }, { translateY }]
}
]}
>
{/
Content /}





{/
container element closing tags */}
)

Hi @cvharris. I think that your problem has nothing to do with TypeScript so I suggest you to open a new issue to get better feedback and more attention.

722 fixes transform for me. Any plans on merging this?

Yeah, it was reviewed, so I'll merge it.

"@types/react-native": "^0.57.61" -> works.
"@types/react-native": "^0.62.11" -> not works

Error message

Type '{ style: (false | 0 | ViewStyle | RegisteredStyle<ViewStyle> | RecursiveArray<false | ViewStyle | RegisteredStyle<ViewStyle> | null | undefined> | ... 4 more ... | undefined)[]; ... 54 more ...; children: ReactNode; }' is not assignable to type '{ hitSlop?: WithAnimatedValue<Insets | undefined> | undefined; onLayout?: WithAnimatedValue<((event: LayoutChangeEvent) => void) | undefined> | undefined; ... 52 more ...; key?: WithAnimatedValue<...> | undefined; }'.
  Types of property 'ref' are incompatible.
    Type '((instance: View | null) => void) | RefObject<View> | null | undefined' is not assignable to type 'WithAnimatedValue<((instance: View | null) => void) | RefObject<View> | null | undefined> | undefined'.
      Type 'null' is not assignable to type 'WithAnimatedValue<((instance: View | null) => void) | RefObject<View> | null | undefined> | undefined'.

Code

import * as React from 'react';
import { Animated, StyleSheet, View, StyleProp, ViewStyle } from 'react-native';
import shadow from './shadow';
import Colors from '@/constants/Colors';

type Props = React.ComponentPropsWithRef<typeof View> & {
  children: React.ReactNode;
  style?: StyleProp<ViewStyle>;
};

class Surface extends React.Component<Props> {
  render() {
    const { style, ...rest } = this.props;
    const flattenedStyles = StyleSheet.flatten(style) || {};
    const { elevation = 4 }: ViewStyle = flattenedStyles;
    return (
      <Animated.View
        {...rest}
        style={[
          {
            backgroundColor: Colors.surface,
          },
          elevation && shadow(elevation),
          style,
        ]}
      />
    );
  }
}
export default Surface;

{...rest} overload causing the trouble.

723 Must solve the problem. But have conflicting files.

@jaikme, you're using reanimated from master branch or some specific version?

Uh, Sorry to bother u guys, I think it was a false alarm.
Despite having react-native-reanimated@^1.8.0 installed as a dependency in my project, I was not using it in the implementation of the component. I am not clear enough, but my problem is related to the @types/react-native typing.

1.9.0 release solved the transform types issue for my project.

Was this page helpful?
0 / 5 - 0 ratings