score:4

Accepted answer
import React, { useRef, createElement } from "react";

type ElementProps<Tag> = Tag extends keyof JSX.IntrinsicElements
  ? JSX.IntrinsicElements[Tag]
  : never;

type Values<T> = T[keyof T];

type ObtainHTMLProps<T extends Values<JSX.IntrinsicElements>> =
  T extends React.DetailedHTMLProps<infer Props, HTMLElement> ? Props : never;

type AllowedProps = Values<{
  [Tag in keyof JSX.IntrinsicElements]: {
    tagName: Tag;
  } & ObtainHTMLProps<JSX.IntrinsicElements[Tag]>;
}>;  

const Editable: React.FC<AllowedProps> = ({ tagName = "div", ...props }) => {
  const htmlEl = useRef(null);

  const elementProps: ElementProps<typeof tagName> = {
    ...props,
    ref: htmlEl,
  };

  return createElement(tagName, elementProps);
};

const canvas = <Editable tagName="canvas" width={20} /> // ok
const anchor = <Editable tagName="a" href={'www.example.com'} /> // ok

const invalid = <Editable tagName="canvas" href={'www.example.com'} /> // expected error


Related Query

More Query from same tag