Skip to content

[bug]: array or ternary phases in useTransition infer SpringValue<unknown> #2589

Closed

Description

@joshuaellis

beep boop, I'm a bot

Which react-spring target are you using?

  • @react-spring/web
  • @react-spring/three

What version of react-spring are you using?

next (11.0.0-beta.0)

What's Wrong?

When a useTransition phase is an array (a chain), or a ternary between two objects with different keys, the inferred animated state loses its value types. Every key becomes SpringValue<unknown>, so the style can't be passed to an animated element without a cast.

To Reproduce

const transitions = useTransition(items, {
  from: { opacity: 0, height: 0 },
  enter: { opacity: 1, height: 10 },
  leave: [{ opacity: 0 }, { height: 0 }],
})

transitions(style => {
  style.opacity // SpringValue<unknown>, expected SpringValue<number>
  return <animated.div style={style} /> // type error
})

The same happens with leave: flag ? { opacity: 0 } : { opacity: 0, x: 10 }. useSpring with an array to is not affected.

Expected Behaviour

style.opacity is SpringValue<number>, and the style can be passed to an animated element.

Cause

TypeScript types a mixed array literal or ternary as a union in which each member marks the other members' keys as optional undefined: ({ opacity: number; height?: undefined } | { opacity?: undefined; height: number })[]. ObjectFromUnion in packages/types/src/utils.ts takes its keys from keyof Intersect<T>. Because number & undefined is never, the intersection collapses to never and every key maps to unknown.

Link to repo

Found while building the usePresenceList demos for #2540: the multistage-transition and upload-queue sandboxes both hit it. The new hooks use the same inference, so they have the same problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions