Skip to content

Instantly share code, notes, and snippets.

@bvisness
Created December 30, 2025 18:55
Show Gist options
  • Select an option

  • Save bvisness/a52aa9275a95890b8df068a20ac366eb to your computer and use it in GitHub Desktop.

Select an option

Save bvisness/a52aa9275a95890b8df068a20ac366eb to your computer and use it in GitHub Desktop.
Simple utilities for creating DOM elements.
/**
* DOM utilities to ease the pain of document.createElement.
*/
type NonNull<T> = T extends null ? never : T;
type CopyNullable<Src, Dst> = Src extends null ? Dst | null : NonNull<Dst>;
type Falsy = null | undefined | false;
/**
* A slightly relaxed Node type for my DOM utilities.
*/
export type BNode = Node | string | null;
/**
* Ensures a DOM Node.
*/
export function N<T extends BNode>(v: T): CopyNullable<T, Node> {
if (typeof v === "string") {
return document.createTextNode(v);
}
return v as any;
}
/**
* Adds children to a DOM node.
*/
export function addChildren(n: Node, children: BNode[]) {
for (const child of children) {
if (child) {
n.appendChild(N(child));
}
}
}
export function E<K extends keyof HTMLElementTagNameMap>(
type: K,
classes?: (string | Falsy)[],
init?: (el: HTMLElementTagNameMap[K]) => void,
children?: BNode[],
): HTMLElementTagNameMap[K];
export function E(
type: string,
classes?: (string | Falsy)[],
init?: (el: HTMLElement) => void,
children?: BNode[],
): HTMLElement;
/**
* Creates a DOM element.
* @param type The type of DOM element to create (e.g. `"div"`)
* @param classes Any classes to add to the element
* @param children Any children to add to the element
*/
export function E(
type: string,
classes?: (string | Falsy)[],
init?: (el: HTMLElement) => void,
children?: BNode[],
) {
const el = document.createElement(type);
if (classes && classes.length > 0) {
const actualClasses: string[] = classes.filter((c): c is string => !!c);
el.classList.add(...actualClasses);
}
init?.(el);
if (children) {
addChildren(el, children);
}
return el;
}
/**
* Creates a DOM fragment.
* @param children
*/
export function F(children: BNode[]): DocumentFragment {
const f = document.createDocumentFragment();
addChildren(f, children);
return f;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment