【问题标题】:Typescript definitions for Animated.View's style propAnimated.View 的样式道具的打字稿定义
【发布时间】:2019-01-02 10:40:34
【问题描述】:

我有一个组件,其 Props 接口从 React Native 扩展 ViewProps,即:

export interface Props extends ViewProps {
  // Custom props
}

当然,这扩展了 style 属性。有一个警告,我使用的是Animated.View 并且有这样的风格:

style={{
  opacity: animationCharacter.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1]
  }),
  transform: [
    {
      scale: animationCharacter.interpolate({
        inputRange: [0, 1],
        outputRange: [1.2, 1]
      })
    }
  ]
}}

我认为interpolate 调用与来自ViewProps 的样式类型不兼容,但没有可以扩展的AnimatedViewProps

这里有解决方案还是我必须设置style: any

【问题讨论】:

标签: typescript react-native typescript-typings


【解决方案1】:

我不相信有内置的解决方案。看看the type definitions for React Native,Animated 命名空间甚至没有指定 Animated 组件的类型,而just leaves them as any

/**
 * Animated variants of the basic native views. Accepts Animated.Value for
 * props and style.
 */
export const View: any;
export const Image: any;
export const Text: any;
export const ScrollView: any;

即使是 React Native 源(使用 FlowType)也将 props 留给 plain Object type

class AnimatedComponent extends React.Component<Object> {
  …
}

这可能是因为 React Native 具有用于在内部处理动画 stylesprops(甚至是 transforms)的包装类,这使得确切地由于抽象而难以指定类型。我认为你最好的选择是使用any,因为创建你自己的类型会非常乏味,而且几乎没有什么好处。

【讨论】:

【解决方案2】:

我已经制作了“一种”类型,可以将任何视图样式转换为动画样式。

type MaybeAnimated<T> = T | Animated.Value;
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),
    }
  ]
}

你会得到自动建议和动画值的工作。

限制: Animated.Value 引擎盖下的定义只是空类,所以从技术上讲,一切都会匹配它。因此,您将能够为其分配不正确的值(例如纯字符串而不是数字)

阅读有关推断类型和条件类型的更多信息:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html

【讨论】:

  • 酷!谢谢。 ?
【解决方案3】:

// 从“react-native”导入 {Animated}

interface ImageComponentProps {
  height: Animated.Value;
  width: Animated.Value;
  opacity: Animated.Value;
  uri: string;
}

这对我有用!

【讨论】:

    【解决方案4】:

    像这样的类型定义对我来说很好用:

     const scaleValue = new Animated.Value( 0 );
     const cardScale: Animated.Mapping = scaleValue.interpolate( {
        inputRange: [0, 0.5, 1],
        outputRange: [1, .95, .9],
      } );
     const transformStyle = {transform: [{scale: cardScale}]};
    <TouchableWithoutFeedback
      onPressIn={ () => {
        scaleValue.setValue( 0 );
        Animated.timing( scaleValue, {
          toValue: 1,
          duration: 60,
          easing: Easing.lenear
        } ).start();
       } }
    
       onPressOut={ () => {
        Animated.timing( scaleValue, {
          toValue: 0,
          duration: 550,
          easing: Easing.bounce,
        } ).start();
       } }
    >
      <Animated.View style={ transformStyle }>
        {// some stuff}
      </Animated.View>
    </TouchableWithoutFeedback>
    

    【讨论】:

      【解决方案5】:

      React-Native 库已经为此公开了一些小助手:

      import { Animated } from "react-native";
      
      type AnimatedViewStyle = WithAnimatedValue<ViewStyle>;
      

      【讨论】:

        【解决方案6】:

        @types/react-nativev0.61.9开始,可以使用Animated.AnimatedProps

        以 style 属性为例:

        interface Props {
          style?: Animated.AnimatedProps<StyleProp<ViewStyle>>,
        }
        

        或者获取所有道具:

        export interface Props extends Animated.AnimatedProps<ViewProps> {
          // Custom props
        }
        

        【讨论】:

        • 对我来说,只使用Animated.AnimatedProps&lt;ViewStyle&gt; 解决了这个问题。
        【解决方案7】:

        现有的答案都不适用于我的用例,所以我推出了自己的似乎可行的答案:

        import { RecursiveArray } from "lodash";
        import {
            Animated,
            Falsy,
            ImageStyle,
            RegisteredStyle,
            TextStyle,
            ViewStyle,
        } from "react-native";
        
        export type AnimatedStyleProp<T extends Style> =
            | T
            | AnimatedStyle<T>
            | RegisteredStyle<T>
            | Falsy
            | RecursiveArray<
                | T
                | AnimatedStyle<T>
                | RegisteredStyle<T>
                | Falsy >;
        
        type AnimatedStyle<T extends Style> =
            | T
            | Animated.Value
            | Animated.AnimatedInterpolation
            | Animated.WithAnimatedObject<T>
            | Animated.WithAnimatedArray<T>;
        
        type Style = ViewStyle | TextStyle | ImageStyle;
        

        AnimatedStyleProp&lt;T&gt;StyleProp&lt;T&gt; 的定义完全相同,只是增加了AnimatedStyle&lt;T&gt;

        如果你不使用lodash,这是RecursiveArray&lt;T&gt;的定义(在@types/react-native中使用但不导出):

        interface RecursiveArray<T> extends Array<
            | T
            | ReadonlyArray<T>
            | RecursiveArray<T>
        > {}
        

        【讨论】:

          猜你喜欢
          • 2021-07-11
          • 2021-11-18
          • 2020-11-02
          • 1970-01-01
          • 2020-06-03
          • 2021-12-30
          • 1970-01-01
          • 2021-03-04
          • 1970-01-01
          相关资源
          最近更新 更多