Home > Blockchain >  Custom TouchableOpacity from Pressable TypeScript error
Custom TouchableOpacity from Pressable TypeScript error

Time:08-25

Have this custom TouchableOpacity function component, but for the style prop I'm getting a TS error

import { StyleSheet, Pressable, PressableProps, GestureResponderEvent } from 'react-native';

export default function TouchableOpacity(props: PressableProps) {
  const { style, onPress, children } = props;

  return (
    <Pressable
      onPress={(event: GestureResponderEvent) => {
        onPress?.(event);
      }}
      style={({ pressed }) => [style, pressed ? styles.buttonPressedOpacity : null]}>
      {children}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  buttonPressedOpacity: {
    opacity: 0.5,
  },
});

Here is the complete TS complaint:

TS2322: Type '({ pressed }: PressableStateCallbackType) => (StyleProp | ((state: PressableStateCallbackType) => StyleProp<...>) | { ...; })[]' is not assignable to type 'StyleProp | ((state: PressableStateCallbackType) => StyleProp)'.   Type '({ pressed }: PressableStateCallbackType) => (StyleProp | ((state: PressableStateCallbackType) => StyleProp<...>) | { ...; })[]' is not assignable to type '(state: PressableStateCallbackType) => StyleProp'.     Type '(StyleProp | ((state: PressableStateCallbackType) => StyleProp) | { opacity: number; })[]' is not assignable to type 'StyleProp'.       Type '(StyleProp | ((state: PressableStateCallbackType) => StyleProp) | { opacity: number; })[]' is not assignable to type 'RecursiveArray<ViewStyle | Falsy | RegisteredStyle>'.         The types returned by 'pop()' are incompatible between these types.           Type 'StyleProp | ((state: PressableStateCallbackType) => StyleProp) | { opacity: number; }' is not assignable to type 'ViewStyle | Falsy | RegisteredStyle | RecursiveArray<ViewStyle | Falsy | RegisteredStyle> | readonly (ViewStyle | ... 1 more ... | RegisteredStyle<...>)[]'.             Type '(state: PressableStateCallbackType) => StyleProp' is not assignable to type 'ViewStyle | Falsy | RegisteredStyle | RecursiveArray<ViewStyle | Falsy | RegisteredStyle> | readonly (ViewStyle | ... 1 more ... | RegisteredStyle<...>)[]'. index.d.ts(542, 5): The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & PressableProps & RefAttributes'

CodePudding user response:

The issue here is the type of style which is received from PressableProps and its concatination with the function you provide to the style prop of Pressable. The type of style is as follows:

const style: StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>)

The style is either StyleProp<ViewStyle> or a function that receives a PressableStateCallbackType as an input parameter.

However, the type of the style prop of Pressable is as follows:

PressableProps.style?: StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>)

Thus, the following would work:

<Pressable
  style={style}>
</Pressable>

Since the types match.

However, if you provide the function that receives PressableStateCallbackType yourself and you want to combine this with an additional style, then you have two possibilities.

You know that style is indeed the mentioned function

const _style = style as (pressed: PressableStateCallbackType) => StyleProp<ViewStyle>

<Pressable   
  style={(state) => [_style(state), state.pressed && styles.buttonPressedOpacity]}>
</Pressable>

You know that style is a StyleProp<ViewStyle>

<Pressable
  style={({pressed}) => [style as StyleProp<ViewStyle>, pressed && styles.buttonPressedOpacity]}>
</Pressable>

You do not know

<Pressable
  style={(state) => [typeof style === 'function' ? style(state) : style, state.pressed && styles.buttonPressedOpacity]}>
</Pressable>

Edit: Actually, if you know the type and it is your custom component, then you could change the typing of the props of TouchableOpacity.

  • Related