Skip to content

Instantly share code, notes, and snippets.

@esamattis
Last active June 7, 2022 22:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esamattis/cc998a207710c4999f6f013700bd8444 to your computer and use it in GitHub Desktop.
Save esamattis/cc998a207710c4999f6f013700bd8444 to your computer and use it in GitHub Desktop.
Correctly typed "as" prop for React with working refs
interface ViewProps<T> {
as?: T;
ref?: React.Ref<
T extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[T] : T
>;
children?: React.ReactNode;
}
declare function ViewType<T extends ElementType = "div">(
props: React.ComponentPropsWithoutRef<T> & ViewProps<T>,
): JSX.Element;
export const View: typeof ViewType = forwardRef((props: any, ref) => {
const Component = props.as || "div";
return (
<Component
{...props}
className={"view " + (props.className ?? "")}
ref={ref}
/>
);
}) as any;
Object.assign(View, { displayName: "View" });
function Test() {
return (
<>
<View
as="form"
ref={(e) => {
e?.submit();
e?.value;
e?.disabled;
console.log(e);
}}
onSubmit={() => {}}
onClick={() => {}}
/>
<View
ref={(e) => {
e?.className;
// @ts-expect-error
e?.value;
// @ts-expect-error
e?.disabled;
}}
// @ts-expect-error
disabled
onClick={() => {}}
onSubmit={(e) => {
e.bubbles;
}}
/>
<div
onSubmit={(e) => {
e.bubbles;
}}
></div>
</>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment