Skip to content

Instantly share code, notes, and snippets.

@nsaunders
Created July 14, 2025 14:59
Show Gist options
  • Select an option

  • Save nsaunders/bb58df1282333ce0bf704bcc8b69745d to your computer and use it in GitHub Desktop.

Select an option

Save nsaunders/bb58df1282333ce0bf704bcc8b69745d to your computer and use it in GitHub Desktop.
funel prototype
import type { ComponentProps, ElementType, ReactNode } from "react";
import { createElement } from "react";
export const el = <E extends ElementType>(elementType: E) => {
const ctor = <
P extends
| Record<never, never>
| (unknown extends ComponentProps<E>
? ReactNode
: ComponentProps<E> | ReactNode)
>(
propsOrChild?: P,
...children: P extends { children: unknown } ? never[] : ReactNode[]
) => {
return createElement(
elementType,
...(propsOrChild &&
typeof propsOrChild === "object" &&
!("$$typeof" in propsOrChild)
? [propsOrChild]
: [null, propsOrChild]),
...children
);
};
return new Proxy(ctor, {
get(_target, property) {
return elementType[property as keyof typeof elementType];
},
set(_target, property, value) {
elementType[property as keyof typeof elementType] = value;
return true;
},
}) as E extends string
? typeof ctor
: typeof ctor & {
displayName?: string | undefined;
};
};
export const {
a,
abbr,
address,
area,
article,
aside,
audio,
b,
base,
bdi,
bdo,
blockquote,
body,
br,
button,
canvas,
caption,
cite,
code,
col,
colgroup,
data,
datalist,
dd,
del,
details,
dfn,
dialog,
div,
dl,
dt,
em,
embed,
fieldset,
figcaption,
figure,
footer,
form,
h1,
h2,
h3,
h4,
h5,
h6,
head,
header,
hgroup,
hr,
html,
i,
iframe,
img,
input,
ins,
kbd,
label,
legend,
li,
link,
main,
map,
mark,
menu,
meta,
meter,
nav,
noscript,
object,
ol,
optgroup,
option,
output,
p,
picture,
pre,
progress,
q,
rp,
rt,
ruby,
s,
samp,
script,
search,
section,
select,
slot,
small,
source,
span,
strong,
style,
sub,
summary,
sup,
table,
tbody,
td,
template,
textarea,
tfoot,
th,
thead,
time,
title,
tr,
track,
u,
ul,
var: var_,
video,
wbr,
...missingTags
} = new Proxy(
{} as {
[Tag in keyof HTMLElementTagNameMap]: ReturnType<typeof el<Tag>>;
},
{
get: (_target, tag) => {
if (typeof tag !== "string") {
throw new Error("Tag must be a string");
}
return el(tag as keyof HTMLElementTagNameMap);
},
}
);
({}) satisfies { [P in keyof typeof missingTags]: never };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment