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

React, JSX and refs #30748

Closed
eps1lon opened this issue Apr 4, 2019 · 1 comment
Closed

React, JSX and refs #30748

eps1lon opened this issue Apr 4, 2019 · 1 comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@eps1lon
Copy link
Contributor

eps1lon commented Apr 4, 2019

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms:
react, ref

Code

const genericRef = React.createRef<Element>();
const inputRef = React.createRef<HTMLInputElement>();

// throws, undesired: HTMLInputElement extends Element
<input ref={genericRef} />;
// works, desired
React.createElement("input", { ref: genericRef });
// works, desired
<input ref={inputRef} />;
// works, desired
React.createElement("input", { ref: inputRef });

// throws, undesired: same issue as #1 other motivation
const ElementComponent = React.forwardRef<Element>((_, ref) => (
  <div ref={ref} />
));

// works, desired
<ElementComponent ref={genericRef} />;
// works, desired
React.createElement(ElementComponent, { ref: genericRef });
// works, undesired: inputRef.current.value would be undefined at runtime
<ElementComponent ref={inputRef} />;
// works, undesired: see jsx example
React.createElement(ElementComponent, { ref: inputRef });

Expected behavior:

  • same behavior between JSX and React.createElement
  • undesired behavior gets fixed

Actual behavior:

  • different behavior with and without JSX
  • 2 undesired errors, 1 undesired pass

Playground Link:
https://github.com/eps1lon/typescript-react-ref-issue

Related Issues:
#16019

I suppose the main issue is how react handles refs. Since react never reads the current value it's perfectly fine to pass a less specific type to the ref attribute. I'm not sure if we can express this behavior with types, it is a current limitation that should be fixed or if this is working as intended.

@Jessidhia
Copy link

Yep, it's a long-standing issue in TypeScript. We were able to avoid it for the most part back when the only typesafe refs would be functions, because there is a hack we can use to get TypeScript to treat function parameters as bivariant; but there is no way to tell TypeScript that the "ref" prop actually is contravariant (hopefully I'm using the right computer science term).

I wrote about it in #10717 (comment) but issues about that go as far back as #1394

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants