//@flow
const React = require('react');

type Props = {|foo: number|};
const FancyButton = React.forwardRef<Props, HTMLButtonElement>((props, ref) => (
  <button ref={ref} className="FancyButton"></button>
));

FancyButton as React.AbstractComponent<Props, HTMLButtonElement>;

const _a = <FancyButton />; // Error, missing foo
const _b = <FancyButton foo={3} />;
const _c = <FancyButton foo={3} bar={3} />; // Error bar, not allowed in exact props

const goodRef = React.createRef<HTMLButtonElement>();
const _d = <FancyButton foo={3} ref={goodRef} />;

const badRef = React.createRef<HTMLDivElement>();
const _e = <FancyButton foo={3} ref={badRef} />; // Incorrect ref type

const _f = <FancyButton foo={3} ref={x => x} />;
const _g = <FancyButton foo={3} ref={(x: null | HTMLDivElement) => x} />; // Incorrect ref type

type FooProps = {|foo: number|};

const UnionRef = React.forwardRef<
  FooProps,
  HTMLButtonElement | HTMLAnchorElement,
>((props: FooProps, ref): React.Element<'button' | 'a'> => {
  if (props.foo === 0) {
    return <a {...props} ref={ref} />;
  }

  return <button {...props} ref={ref} />;
});

const unionRef = React.createRef<HTMLButtonElement | HTMLAnchorElement>();
const _h = <UnionRef foo={0} ref={unionRef} />;
const _i = <UnionRef foo={1} ref={unionRef} />;

const badUnionRef = React.createRef<HTMLButtonElement | HTMLDivElement>();
const _j = <UnionRef foo={3} ref={badUnionRef} />; // Error bad ref
