Issue 1:
If you know how to fix the issue, make a pull request instead.

I tried using the @types/xxxx package and had problems.

I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript

I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).

Mention the authors (see Definitions by: in index.d.ts) so they can respond.

Authors: @johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @DovydasNavickas @theruther4d @guilhermehubner @ferdaber @jrakotoharisoa @pascaloliv @Hotell @franklixuefei @Jessidhia @saranshkataria @lukyth @eps1lon

Hello! I am facing an issue when trying to type the ref property of a custom component.

This is the setup I have:

// someFile.TS
// Due to some weird Webpack rules and the app's architecture I have this interface in a file which
// cannot import the TableComponent from its TableComponent.tsx file.
// Therefore, I am trying to emulate the end result of the React.createElement function call
interface ITableComponent {
tableProps: IlDataTableProps; // This is the only property I need to access
}

interface ITableComponentProps {
ref: React.RefObject<ITableComponent>
}

// someOtherFile.TSX
class TableComponent extends React.Component<ITableComponentProps> implements ITableComponent {}

// somewhereInTheApp.TSX
class SomeComponent extends ... {
tableRef = React.createRef<ITableComponent>();
render () {
return <TableComponent ref={this.tableRef}/>; // *Read below
}
}

*Over here I get the following error:

Looking through the type definition of ref I came across this line:

type Ref<T> = { bivarianceHack(instance: T | null): void }["bivarianceHack"] | RefObject<T> | null;

and this one:

function createRef<T>(): RefObject<T>;

Seeing as createRef returns a T, in my case that should be ITableComponent. And the ref type also has an option of RefObject<T>. However, as the error shows, it looks for something which is (string & RefObject<T>). I don't understand where that string & is coming for and I also cannot find an explanation why is it needed. To my understanding, the string refs were the first implementation and were deprecated. So why does that type need to interfere with the React.RefObject<T>. Or, if it must interfere, why is it that the React.createRef function is not returning that string & RefObject<T> definition? If I change the definition to that in the @types/react/index.d.ts file everything works as it should.

Issue 2:
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.