Skip to content

React, JSX and refs #30748

@eps1lon

Description

@eps1lon

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions