Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript: Assigning useTransition return value to a prop with type CSSProperties results in 'not assignable' error #1645

Open
DamianPereira opened this issue Jul 23, 2021 · 9 comments
Labels
area: typescript Typescript issues kind: bug Something isn't working

Comments

@DamianPereira
Copy link

DamianPereira commented Jul 23, 2021

🐛 Bug Report

The returned value from useTransition styles is not assignable to a prop with type CSSProperties. The full error is:

TS2322: Type '{ opacity: SpringValue<number>; }' is not assignable to type 'CSSProperties'.   Types of property 'opacity' are incompatible.     Type 'SpringValue<number>' is not assignable to type 'Opacity | undefined'.       Type 'SpringValue<number>' is not assignable to type 'number & {}'.         Type 'SpringValue<number>' is not assignable to type 'number'. 

This is probably related to #1102, it seems to keep happening under this scenario.

To Reproduce

Steps to reproduce the behavior:
Using this code (or any component which receives styles as a prop with type CSSProperties):

const AnimatedTest = ({ styles }: { styles: CSSProperties }) => (
  <animated.div style={styles}>Test</animated.div>
);

export default function App() {
  const [items, setItems] = useState([]);
  const transitions = useTransition(items, {
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
    delay: 200,
  });

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      {transitions((styles) => <AnimatedTest styles={styles}/>)}
    </div>
  );
}

Expected behavior

There should be no compilation error since the type returned from useTransition should be compatible with CSSProperties.

Link to repro (highly encouraged)

Codesandbox link

Environment

  • react-spring v9.2.4
  • react v17.0.3
@joshuaellis joshuaellis added template: bug This issue might be a bug area: typescript Typescript issues labels Aug 2, 2021
@joshuaellis
Copy link
Member

Please create a reproduction of the issue in a sandbox for review.

@joshuaellis joshuaellis added the type: needs repro Needs minimal reproduction label Aug 4, 2021
@DamianPereira
Copy link
Author

I'm sorry, the link was wrong, I meant to link to this sandbox, which has the issue.

@joshuaellis joshuaellis added this to the v9.4.0 milestone Oct 10, 2021
@DerekLoop
Copy link

DerekLoop commented Oct 20, 2021

This workaround helped me in the meantime

  const dropdown = useSpring({
    opacity: (showMenu ? 1 : 0) as React.CSSProperties["opacity"],
    pointerEvents: (showMenu
      ? "all"
      : "none") as React.CSSProperties["pointerEvents"],
  })

@joshuaellis
Copy link
Member

Should it be assignable to CSSProperties? You can resolve this by passing SpringValues type. See https://codesandbox.io/s/react-spring-type-bug-forked-netbu?file=/src/App.tsx

@DerekLoop
Copy link

Thanks @joshuaellis that looks like an even-cleaner solution.

@joshuaellis
Copy link
Member

@DamianPereira it'd be good to hear your thoughts on why you think it's an issue since we're not passing CSSProperties, we're passing SpringValues.

@joshuaellis joshuaellis removed the type: needs repro Needs minimal reproduction label Oct 21, 2021
@DerekLoop
Copy link

@joshuaellis My 2 cents are that it should work without needing to cast or specify the type, which would mean returning the correct SpringValues by default 🙂 But this may be challenging to implement.

@joshuaellis
Copy link
Member

It does return SpringValues by default. The original issue is demonstrating that passing the props to another component means you have to cast it with SpringValues not CSSProperties. Unless you have a separate issue @DerekLoop?

@DerekLoop
Copy link

Hi @joshuaellis ! Thanks for the help. Maybe I'm just not understanding the types correctly.

This example works in TypeScript:

  import { animated as a, SpringValues, useSpring } from "@react-spring/web"

  const dropdown = useSpring({
    opacity: (showMenu ? 1 : 0) as React.CSSProperties["opacity"],
    pointerEvents: (showMenu
      ? "all"
      : "none") as React.CSSProperties["pointerEvents"],
  })

  return (<a.div style={dropdown}>Content!</a.div>)

This example gives an error:

  import { animated as a, SpringValues, useSpring } from "@react-spring/web"

  const dropdown = useSpring({
    opacity: showMenu ? 1 : 0,
    pointerEvents: showMenu ? "all" : "none",
  })

  return (<a.div style={dropdown}>Content!</a.div>)

This is the error:

Type '{ opacity: SpringValue<number>; pointerEvents: SpringValue<string>; }' is not assignable to type '{ alignContent?: "initial" | "end" | (string & {}) | "baseline" | "inherit" | "start" | "center" | "-moz-initial" | "revert" | "unset" | "normal" | "space-around" | "space-between" | ... 5 more ... | undefined; ... 802 more ...; matrix3d?: AnimatedObject<...> | undefined; }'.
  Types of property 'pointerEvents' are incompatible.
    Type 'SpringValue<string>' is not assignable to type '"initial" | "all" | "none" | "fill" | "stroke" | "auto" | "inherit" | "-moz-initial" | "revert" | "unset" | "painted" | "visible" | "visibleFill" | "visiblePainted" | "visibleStroke" | FluidValue<...> | undefined'.
      Type 'SpringValue<string>' is not assignable to type 'FluidValue<NonObject<PointerEvents | undefined>, any>'.
        The types returned by 'get()' are incompatible between these types.
          Type 'string' is not assignable to type 'NonObject<PointerEvents | undefined>'.ts(2322)
index.d.ts(1841, 9): The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & AnimatedProps<{ onChange?: FormEventHandler<HTMLDivElement> | undefined; onPause?: ReactEventHandler<HTMLDivElement> | undefined; ... 253 more ...; ref?: RefObject<...> | ... 2 more ... | undefined; }> & { ...; }'
(JSX attribute) style?: {
    alignContent?: "end" | (string & {}) | "baseline" | "inherit" | "initial" | "start" | "center" | "-moz-initial" | "revert" | "unset" | "normal" | "space-around" | "space-between" | ... 5 more ... | undefined;
    ... 802 more ...;
    matrix3d?: AnimatedObject<...> | undefined;
} | undefined

This example also works without an error:

  import { animated as a, SpringValues, useSpring } from "@react-spring/web"

  const dropdown = useSpring({
    opacity: showMenu ? 1 : 0,
    pointerEvents: showMenu ? "all" : "none",
  }) as SpringValues<{ opacity: number; pointerEvents: "all" | "none" }>


  return (<a.div style={dropdown}>Content!</a.div>)

I'm just not sure why casting is necessary in either case 🎃😅 Though the SpringValues solution seems more correct.

@joshuaellis joshuaellis added kind: bug Something isn't working and removed template: bug This issue might be a bug labels Dec 21, 2021
@joshuaellis joshuaellis modified the milestone: v9.4.0 Jan 3, 2022
cameron-martin pushed a commit to cameron-martin/react-spring that referenced this issue May 10, 2022
@pmndrs pmndrs deleted a comment from joshi-sanjay Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: typescript Typescript issues kind: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants