Shopify / restyle

A type-enforced system for building UI components in React Native with TypeScript.

Home Page:https://shopify.github.io/restyle/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect TS definition for useRestyle hook

antoinebugni opened this issue · comments

After installing the library via yarn install the typescript definition for useRestyle looks like this:

import { StyleProp } from 'react-native';
import { BaseTheme, RestyleFunctionContainer, RNStyle } from '../types';

declare const useRestyle: <Theme extends BaseTheme, TRestyleProps extends Record<string, any>, TProps extends TRestyleProps & {
    style?: StyleProp<RNStyle>;
}>(restyleFunctions: (RestyleFunctionContainer<TProps, Theme, keyof TProps, keyof Theme | undefined> | RestyleFunctionContainer<TProps, Theme, keyof TProps, keyof Theme | undefined>[])[], props: TProps) => Pick<TProps, Exclude<keyof TProps, keyof TProps>>;

export default useRestyle;

The return type Pick<TProps, Exclude<keyof TProps, keyof TProps>> seems incorrect as this always results in:

<Pick<TProps, never>> (which is the equivalent of {})

I imagine the intended behaviour is closer to something like:

Pick<TProps, Exclude<keyof TProps, keyof TRestyleProps>>

Apologies if I'm missing anything obvious 🙏

I am not sure if this is related, but I get a TS2345 error when I use the useRestyle hook. So maybe this is caused by this faulty return type.

import { layout, spacing, useRestyle } from '@shopify/restyle';
import React from 'react';

const restyleFunctions = [layout, spacing];

const Button: React.FC<Props> = (props) => {
  const { ...rest } = props;
  const themeProps = useRestyle(restyleFunctions, rest);
                                ^^^^^^^^^^^^^^^^
                                TS2345: see the (absolutely not helpful) error message in the screenshot below
};

TS2345

I am not sure if this is related, but I get a TS2345 error when I use the useRestyle hook. So maybe this is caused by this faulty return type.

import { layout, spacing, useRestyle } from '@shopify/restyle';
import React from 'react';

const restyleFunctions = [layout, spacing];

const Button: React.FC<Props> = (props) => {
  const { ...rest } = props;
  const themeProps = useRestyle(restyleFunctions, rest);
                                ^^^^^^^^^^^^^^^^
                                TS2345: see the (absolutely not helpful) error message in the screenshot below
};
TS2345

@Spielboerg I don't think that's related, I think this might be a problem with the definition of the Props type in your example - but the definition is missing so I can't say for sure.

@antoinebugni Yes, you are right. "rest" was not typed correctly. Thank you.

Alter upgrade to version 2 i'm experiencing the same problem.

const buttonStyleFunctions = composeRestyleFunctions([
    spacing,
    border,
    backgroundColor,
]);
const titleStyleFunctions = composeRestyleFunctions([typography]);

type RNEButtonPropsExcluded = Exclude<RNEButtonProps, "buttonStyle">;
type Props = RNEButtonPropsExcluded & {
    buttonStyle?: SpacingProps<Theme> & 
        BorderProps<Theme> &
        BackgroundColorProps<Theme>;
    titleStyle?: TypographyProps<Theme>;
    color?: keyof Theme["colors"];
};

export const Button = ({ buttonStyle, titleStyle, color, ...rest }: Props) => {
    const theme = useTheme<Theme>();

    const reStyledButton = useRestyle(buttonStyleFunctions, buttonStyle || {});

    const reStyledButtonStyles = reStyledButton.style as StyleProp<ViewStyle>;

    const reStyledTitle = useRestyle(titleStyleFunctions, titleStyle || {});

    // @ts-ignore
    const { style, ...textProps } = reStyledTitle as StyleProp<ViewStyle>;

    return (
        <RNEButton
            {...rest}
            buttonStyle={reStyledButtonStyles}
            titleStyle={[
                ...style,
                {
                    ...textProps,
                    color: color ? theme.colors[color] : undefined,
                },
            ]}
        />
    );
};

image

I have the same problem as @bearkfear:

import {
  composeRestyleFunctions,
  spacing,
  SpacingProps,
  useRestyle
} from "@shopify/restyle";
import * as React from "react";
import { Pressable, StyleSheet } from "react-native";
import { Theme } from "../theme";
import Box from "./box";
import Text from "./text";

const restyleFunctions = composeRestyleFunctions([spacing]);
const styles = StyleSheet.create({
  pressable: {
    borderRadius: 8
  }
});

type Props = SpacingProps<Theme> & { text: string; onPress: () => void };

function Button({ text, onPress, ...rest }: Props) {
  const props = useRestyle(restyleFunctions, rest);

  return (
    <Box flex={1} {...props}>
      <Pressable style={styles.pressable} onPress={onPress}>
        <Box
          flex={1}
          height={44}
          paddingHorizontal="m"
          alignItems="center"
          justifyContent="center"
          backgroundColor="buttonBackground"
          borderRadius={8}>
          <Text variant="button">{text}</Text>
        </Box>
      </Pressable>
    </Box>
  );
}

export default Button;

Screenshot 2022-03-23 at 09 48 56

The error is:

Argument of type '{ buildStyle: (props: Record<string, any>, { theme, dimensions, }: { theme: BaseTheme; dimensions: Dimensions; }) => RNStyle; properties: string[]; propertiesMap: Record<...>; }' is not assignable to parameter of type '{ buildStyle: <TInputProps extends { margin?: ResponsiveValue<"m" | "s" | "l" | "xl", { colors: { mainBackground1: string; mainBackground2: string; tabBarBackground: string; tabBarInactiveForeground: string; tabBarActiveForeground: string; ... 6 more ...; buttonBackground: string; }; spacing: { ...; }; breakpoints: ...'.
  Types of property 'properties' are incompatible.
    Type 'string[]' is not assignable to type '("margin" | "marginBottom" | "marginEnd" | "marginHorizontal" | "marginLeft" | "marginRight" | "marginStart" | "marginTop" | "marginVertical" | "padding" | "paddingBottom" | ... 6 more ... | "paddingVertical")[]'.
      Type 'string' is not assignable to type '"margin" | "marginBottom" | "marginEnd" | "marginHorizontal" | "marginLeft" | "marginRight" | "marginStart" | "marginTop" | "marginVertical" | "padding" | "paddingBottom" | ... 6 more ... | "paddingVertical"'.ts(2345)

@bearkfear and @JuanjoFR - I don't think either of the TS errors you're experiencing here are related to this issue.

@bearkfear I can't be 100% sure for you because you've not shared the actual error
@JuanjoFR your error is related to some issue with the definition of restyleFunctions

To give you an example to illustrate the issue I raised, take the following code:

import React from 'react';
import { Image, ImageProps } from 'react-native';

import { Theme } from '@sf/styles';

export const restyleFunctions = [backgroundColor];

/** Image component */
export type MyComponentProps = ImageProps & AllProps<Theme>;
export const MyComponent: React.FC<MyComponentProps> = props => {
  const restyleProps = useRestyle(restyleFunctions, props);
  return <Image {...restyleProps} />;
};

☝️ this results in the following error 👇 :

No overload matches this call.
  Overload 1 of 2, '(props: ImageProps | Readonly<ImageProps>): Image', gave the following error.
    Property 'source' is missing in type '{}' but required in type 'Readonly<ImageProps>'.
  Overload 2 of 2, '(props: ImageProps, context: any): Image', gave the following error.
    Property 'source' is missing in type '{}' but required in type 'Readonly<ImageProps>'.ts(2769)

The definition of props returned by useRestyle is {} - which may cause issue depending on the component. In this example, the source prop is mandatory but missing in the TS definition for the value returned by useRestyle.

I hope that's a bit clearer for everyone, sorry if this was confusing at all.

Hello @sbalay ! same problem here, I have a incorrect type definition with useRestyle =>

here an example https://snack.expo.dev/@ludwig-pro/expo-typescript-restyle

there are two components :

  • RestyleButton.tsx (a copy / paste of the README )
  • RestyleBox.tsx - a custom box to handle opacity props

image

@antoinebugni I believe that the issue you reported here could be solved by upgrading to the latest version of restyle (and following the migration guide)

@ludwig-vaan your issue seems a regression introduced by https://github.com/Shopify/restyle/pull/138/files, we'll try to find a solution or revert that PR. Could you create a new issue?

@sbalay I did upgrade our repo to the latest version recently and forgot to check - indeed you're right, the issue is resolved :) Thanks for pointer!

@ludwig-vaan your issue seems a regression introduced by https://github.com/Shopify/restyle/pull/138/files, we'll try to find a solution or revert that PR. Could you create a new issue?

For posterity, @ludwig-vaan did open an issue here: #159

I'm facing the same issue with @ludwig-vaan , the newest version 2.3.0 didn't resolve it yet. any suggestions?