Definitelytyped: [react-native] support Animated.Value in properties

Created on 24 Oct 2016  路  18Comments  路  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the latest react-native/react-native.d.ts file in this repo and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).

All the properties in ViewStyle do not support Animated.value. Is it a good idea to add animation support to the type definition?

For example, tsc will report error on this code snippet:

someStyle: {
    opacity: new Animated.Value(0),
}

Most helpful comment

This seems to be supported in the latest types:

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/aa4ea25/types/react-native/index.d.ts#L8770

They're still a bit buggy, but better than nothing!

All 18 comments

please send a pull request. I'll review it.

There should probably be a Animated.ViewStyle for Animated.View indeed. Please do submit a PR.

@hktonylee Did you have any solution now. I get error by setting Animated.View's style type as ViewStyle, in .d.ts Animated.View: any;

@vonweb Sorry I don't have solution right now. Thanks for reminding me about this problem and I will revisit it later.

@vonweb a temp solution to get rid of typescript errors is to cast twice like this, though you lose type safety:

const style = {
  opacity: new Animated.Value(0)
} as any as ViewStyle

I notice this issue has been for more than a year and I tried to change the definition myself, trying to understand what the problem is. I got a lot of red and I am not sure why.

( below was my stupid attempt to "fix" it)

export interface ViewStyle extends FlexStyle, TransformsStyle {
  ...
  opacity?:  number | Animated.Value; // no?... nop.. :(
}

I guess not many try to do animations in react native with typescript :(

We have this issue too :,( sucks this issue has been open for two years now.
@rodrigoelp I think you are on the right track. I'm unsure what all style attributes support Animated.Value. I also don't know what the ramification are to adding it like that, since the animated values are only valid on for example Animated.View and not View.

Our current workaround (our use case is specific to Text):

type ExtendedTextStyles = StyleProp<{
  [key in keyof TextStyle] : Animated.Value | TextStyle[key];
}>

then

interface FontStyleWrapperProps {
  children: (styles: TextStyle) => React.ReactElement<{}>;
  style: ExtendedTextStyles;
}

const FontStyleWrapper = ({ style, children }: FontStyleWrapperProps) => {
  const flatStyle = StyleSheet.flatten(style as StyleProp<TextStyle>);
  //....
  return children(styles);
};

also, these types don't seem to be correct either--they should be number | Animated.Value:

export interface TransformsStyle {
    transform?: (
        | PerpectiveTransform
        | RotateTransform
        | RotateXTransform
        | RotateYTransform
        | RotateZTransform
        | ScaleTransform
        | ScaleXTransform
        | ScaleYTransform
        | TranslateXTransform
        | TranslateYTransform
        | SkewXTransform
        | SkewYTransform)[];
    transformMatrix?: Array<number>;
    rotation?: number;
    scaleX?: number;
    scaleY?: number;
    translateX?: number;
    translateY?: number;
}

I can open a pr for that one

Hi @stantoncbradley, I end up applying the style directly to the object as part of my declaration.

You can find some of my sample code here. Unfortunately, I tried to understand with proper examples in typescript but I couldn't find that many online (which is a true shame).

@rodrigoelp thanks for sharing! These values still look like they are of type Animated.Value. how does does that get validated against Animated.View's style type, which doesn't support Animated.Value?

If you check the type definition, they extend some objects in the Animated namespace, in which the definition redeclares View as any... (effectively allowing any definition).

I imagine once you start including new stuff there typescript has no way of validating it anymore.

The definition of Animated starts here

And the redefinition of View is here

I might be wrong, but I understood how to use the api by reading the tests (extremely unproductive way of telling you how to extend the animation)

@rodrigoelp ok I finally figured it out, thanks your comments were very helpful!
For anyone else who ends up here, the Animated types are correct, if a little confusing.
As it stands, all the View, Text, and Image styles only apply to those components, not to their animated counterparts (ie Animated.View). That's because, as @rodrigoelp pointed out, Animated redefines Animated.View, Animated.Text, and Animated.Image as type any. So, for example, the TransformsStyles that are listed as type number when I would expect type Animated.Value, ie translateX?: number;, is correct, because this is the only valid type for translateX on the non-animated components, and the animated components use type any, so they don't even use the TransformsStyles type at all. I closed my PR above, and think this issue can be closed as well.

I've made 'kind of' type that converts any view styles into animatable styles.

type MaybeAnimated<T> = T | Animated.Value | Animated.AnimatedInterpolation;
type AnimatedScalar = string | number;

type AnimatedStyles<T> = {
  [Key in keyof T]: T[Key] extends AnimatedScalar
    ? MaybeAnimated<T[Key]>
    : T[Key] extends Array<infer U>
    ? Array<AnimatedStyles<U>>
    : AnimatedStyles<T[Key]>
};

type ViewAnimatedStyles = AnimatedStyles<ViewStyle>;

const test: ViewAnimatedStyles = {
  transform: [
    {
      rotateY: new Animated.Value(2),
    }
  ]
}

You get auto-suggestions and animated values work.

Limitation:
Animated.Value definition under the hood is just empty class so technically, everything will match it. So you'll be able to assign an incorrect value to it (eg plain string instead of number)

image

Read more about infered and conditional types: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html

Hello My friend
why Animated.Value and Animated.timing are ((Unresolved type Value))
and my code not run

/** @format */
import { AppRegistry} from 'react-native';
import React from 'react';
import {View,Image , Animated} from 'react-native';

class App extends React.Component{
constructor(props){
super(props);

    this.spinValue = new Animated.Value(0)
}
componentWillMount(){
    Animated.timing(this.spinValue,{
        toValue: 1,
        duration: 3000,
    }).start();
}

render(){
    const spin = this.spinValue.interpolate({
        inputRange: [0,1],
        outputRange: ['0deg', '360deg']
    });
   return(
       <View style={{flex:1,justifyContent:'center', alignItems:'center'}}>
           <Image source={require('./src/images/a.png')} style={{width:100,height:100, transform:[{ rotate: spin }]}}/>
       </View>
   )
}

}

AppRegistry.registerComponent('ReactApp', () => App);

This seems to be supported in the latest types:

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/aa4ea25/types/react-native/index.d.ts#L8770

They're still a bit buggy, but better than nothing!

@hsource Thanks for the bump, in the interest of repo hygiene I鈥檒l close this 馃檹

@hsource Oh and if you have specific cases that are buggy but don鈥檛 know of a fix; a PR that adds test cases illustrating the issue(s) is a great first step towards solving this together.

Was this page helpful?
0 / 5 - 0 ratings