Skip to content

Commit

Permalink
[react] Port ElementRef utility type from Flow
Browse files Browse the repository at this point in the history
  • Loading branch information
alloy committed Mar 18, 2020
1 parent 8770afc commit de1592a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
26 changes: 26 additions & 0 deletions types/react/index.d.ts
Expand Up @@ -90,6 +90,32 @@ declare namespace React {
type RefCallback<T> = { bivarianceHack(instance: T | null): void }["bivarianceHack"];
type Ref<T> = RefCallback<T> | RefObject<T> | null;
type LegacyRef<T> = string | Ref<T>;
/**
* Gets the instance type for a React element. The instance will be different for various component types:
*
* - React class components will be the class instance. So if you had `class Foo extends React.Component<{}> {}`
* and used `React.ElementRef<typeof Foo>` then the type would be the instance of `Foo`.
* - React stateless functional components do not have a backing instance and so `React.ElementRef<typeof Bar>`
* (when `Bar` is `function Bar() {}`) will give you the `undefined` type.
* - JSX intrinsics like `div` will give you their DOM instance. For `React.ElementRef<'div'>` that would be
* `HTMLDivElement`. For `React.ElementRef<'input'>` that would be `HTMLInputElement`.
*
* `C` must be the type _of_ a React component so you need to use typeof as in React.ElementRef<typeof MyComponent>.
*/
type ElementRef<
C extends
| ComponentClass<any>
| FunctionComponent<any>
| keyof JSX.IntrinsicElements
> = C extends ComponentClass<any>
? InstanceType<C>
: C extends FunctionComponent<any>
? undefined
: C extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[C] extends DOMAttributes<infer E>
? E
: never
: never;

type ComponentState = any;

Expand Down
5 changes: 5 additions & 0 deletions types/react/test/index.ts
Expand Up @@ -440,6 +440,11 @@ function RefCarryingComponent() {
);
}

type RefComponentAsRef = React.ElementRef<typeof RefComponent>; // $ExpectType RefComponent
type RefCarryingComponentAsRef = React.ElementRef<typeof RefCarryingComponent>; // $ExpectType undefined
type HTMLIntrinsicAsRef = React.ElementRef<'div'>; // $ExpectType HTMLDivElement
type SVGIntrinsicAsRef = React.ElementRef<'svg'>; // $ExpectType SVGSVGElement

//
// Attributes
// --------------------------------------------------------------------------
Expand Down

0 comments on commit de1592a

Please sign in to comment.