3

I am trying to implement typescript into my project and I am having issues giving prop types to my swipe prop. They are both the correct type but when giving this type I get an error on line 72:

style={[styles.container, isFirst && animatedCardStyle]}

The error says: Type 'false | { transform: ({ [key: string]: Value; } | { rotate: AnimatedInterpolation; })[]; }' is not assignable to type 'false | Value | AnimatedInterpolation | RegisteredStyle | WithAnimatedObject | WithAnimatedArray<...> | readonly (false | ... 5 more ... | undefined)[] | null | undefined'.   Type '{ transform: ({ [key: string]: Animated.Value; } | { rotate: Animated.AnimatedInterpolation; })[]; }' is not assignable to type 'false | Value | AnimatedInterpolation | RegisteredStyle | WithAnimatedObject | WithAnimatedArray<...> | readonly (false | ... 5 more ... | undefined)[] | null | undefined'.     Type '{ transform: ({ [key: string]: Animated.Value; } | { rotate: Animated.AnimatedInterpolation; })[]; }' is not assignable to type 'WithAnimatedObject'.       The types returned by 'transform.pop()' are incompatible between these types.         Type '{ [key: string]: Value; } | { rotate: AnimatedInterpolation; } | undefined' is not assignable to type 'WithAnimatedObject | WithAnimatedObject | WithAnimatedObject | ... 10 more ... | undefined'.           Type '{ [key: string]: Value; }' is not assignable to type 'WithAnimatedObject | WithAnimatedObject | WithAnimatedObject | ... 10 more ... | undefined'.             Property 'matrix' is missing in type '{ [key: string]: Value; }' but required in type 'WithAnimatedObject'. index.d.ts(818, 5): 'matrix' is declared here.

I am really confused what this means, although my app runs and works I dont know the error, I can use the any type too and it clears this issue up too. Any help would be great!

import React, {useCallback} from 'react';
    import {LinearGradient} from 'expo-linear-gradient';
    import {Animated, Image, ImageSourcePropType, Text} from 'react-native';
    import Choice from '../Choice';
    import {ACTION_OFFSET} from '../Utils/constants';
    
    import {styles} from './styles';
    
    type Props = {
        name: string,
        source: ImageSourcePropType,
        isFirst: boolean,
        swipe: Animated.AnimatedValueXY,
        tiltSign: Animated.AnimatedValue,
    };
    const Card = ({
                      name,
                      source,
                      isFirst,
                      swipe,
                      tiltSign,
                      ...rest
                  }: Props) => {
        const rotate = Animated.multiply(swipe.x, tiltSign).interpolate({
            inputRange: [-ACTION_OFFSET, 0, ACTION_OFFSET],
            outputRange: ['8deg', '0deg', '-8deg'],
        });
    
        const likeOpacity = swipe.x.interpolate({
            inputRange: [25, ACTION_OFFSET],
            outputRange: [0, 1],
            extrapolate: 'clamp',
        });
    
        const nopeOpacity = swipe.x.interpolate({
            inputRange: [-ACTION_OFFSET, -25],
            outputRange: [1, 0],
            extrapolate: 'clamp',
        });
    
        const animatedCardStyle = {
            transform: [...swipe.getTranslateTransform(), {rotate}],
        };
    
        const renderChoice = useCallback(() => {
            return (
                <>
                    <Animated.View
                        style={[
                            styles.choiceContainer,
                            styles.likeContainer,
                            {opacity: likeOpacity},
                        ]}
                    >
                        <Choice type="like"/>
                    </Animated.View>
                    <Animated.View
                        style={[
                            styles.choiceContainer,
                            styles.nopeContainer,
                            {opacity: nopeOpacity},
                        ]}
                    >
                        <Choice type="nope"/>
                    </Animated.View>
                </>
            );
        }, [likeOpacity, nopeOpacity]);
    
        return (
            <Animated.View
                style={[styles.container, isFirst && animatedCardStyle]}
                {...rest}
            >
                <Image source={source} style={styles.image}/>
                <LinearGradient
                    colors={['transparent', 'rgba(0,0,0,0.9)']}
                    style={styles.gradient}
                />
                <Text style={styles.name}>{name}</Text>
    
                {isFirst && renderChoice()}
            </Animated.View>
        );
    }
    
    export default Card;
Oliver Darby
  • 454
  • 1
  • 6
  • 15

2 Answers2

2

The best way I have found to fix it is to give the animatedCardStyle a type of Animated.Animated and this clears up the error.

import React, {useCallback} from 'react';
import {LinearGradient} from 'expo-linear-gradient';
import {Animated, Image, ImageSourcePropType, Text} from 'react-native';
import Choice from '../Choice';
import {ACTION_OFFSET} from '../Utils/constants';

import {styles} from './styles';

type Props = {
    name: string,
    source: ImageSourcePropType,
    isFirst: boolean,
    swipe: Animated.ValueXY,
    tiltSign: Animated.Value,
};
const Card = ({
                  name,
                  source,
                  isFirst,
                  swipe,
                  tiltSign,
                  ...rest
              }: Props) => {
    const rotate = Animated.multiply(swipe.x, tiltSign).interpolate({
        inputRange: [-ACTION_OFFSET, 0, ACTION_OFFSET],
        outputRange: ['8deg', '0deg', '-8deg'],
    });

    const likeOpacity = swipe.x.interpolate({
        inputRange: [25, ACTION_OFFSET],
        outputRange: [0, 1],
        extrapolate: 'clamp',
    });

    const nopeOpacity = swipe.x.interpolate({
        inputRange: [-ACTION_OFFSET, -25],
        outputRange: [1, 0],
        extrapolate: 'clamp',
    });

    const animatedCardStyle: Animated.Animated = {
        transform: [...swipe.getTranslateTransform(), {rotate}],
    };

    const renderChoice = useCallback(() => {
        return (
            <>
                <Animated.View
                    style={[
                        styles.choiceContainer,
                        styles.likeContainer,
                        {opacity: likeOpacity},
                    ]}
                >
                    <Choice type="like"/>
                </Animated.View>
                <Animated.View
                    style={[
                        styles.choiceContainer,
                        styles.nopeContainer,
                        {opacity: nopeOpacity},
                    ]}
                >
                    <Choice type="nope"/>
                </Animated.View>
            </>
        );
    }, [likeOpacity, nopeOpacity]);

    return (
        <Animated.View
            style={[styles.container, isFirst && animatedCardStyle]}
            {...rest}
        >
            <Image source={source} style={styles.image}/>
            <LinearGradient
                colors={['transparent', 'rgba(0,0,0,0.9)']}
                style={styles.gradient}
            />
            <Text style={styles.name}>{name}</Text>

            {isFirst && renderChoice()}
        </Animated.View>
    );
}

export default Card;
Oliver Darby
  • 454
  • 1
  • 6
  • 15
0

I can break down the chain of the error for you, but the source is honestly really stupid and not your fault.

The error is happening due to an index signature which is what you see is this part of the message Type '{ [key: string]: Value; }' is not assignable to type 'WithAnimatedObject ...

The transform property of your style object needs to be an array where each object is one of these supported transform types. So each object must have one of those properties (scaleX, translateX, etc.).

The getTranslateTransform() method returns an array with a transform for translateX and another for translateY which should be fine, except that the type declaration lists the return type as { [key: string]: AnimatedValue }[]; which is not specific enough. It needs to say that those keys are valid transform properties and not just string.

edit: there is a proposed fix for the bad typing.

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102