Open coolaj86 opened 2 months ago
Some thoughts from Grok2, GPT4o, and Claude:
// Here we go, creating a declaration file for your selector functions
declare function $<Selector extends string, Selected extends Element = HTMLElement>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected | undefined;
declare function $$<Selector extends string, Selected extends Element = HTMLElement>(
selectors: Selector | Selector[],
baseElements?: ParentNode | Iterable<ParentNode>
): Selected[];
// And for those who like to live on the edge with their element selections
declare function expectElement<Selector extends string, Selected extends Element = HTMLElement>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected;
declare function lastElement<Selector extends string, Selected extends Element = HTMLElement>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected | undefined;
declare function elementExists(
selectors: string | string[],
baseElement?: ParentNode
): boolean;
// Exporting these functions for the universe to use
export { $, $$, expectElement, lastElement, elementExists };
// selectors.d.ts
import type { ParseSelector } from 'typed-query-selector/parser.js';
type BaseElements = ParentNode | Iterable<ParentNode>;
export function $<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected | undefined;
export function $<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElement?: ParentNode
): Selected | undefined;
export function $$<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElements?: BaseElements
): Selected[];
export function $$<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElements?: BaseElements
): Selected[];
export function lastElement<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected | undefined;
export function lastElement<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElement?: ParentNode
): Selected | undefined;
export function elementExists(
selectors: string | string[],
baseElement?: ParentNode,
): boolean;
export function expectElement<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected;
export function expectElement<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElement?: ParentNode
): Selected;
export class ElementNotFoundError extends Error {
name: string;
}
// selectors.js
/**
* @typedef {import('./selectors').$} $
* @typedef {import('./selectors').$$} $$
* @typedef {import('./selectors').lastElement} lastElement
* @typedef {import('./selectors').elementExists} elementExists
* @typedef {import('./selectors').expectElement} expectElement
* @typedef {import('./selectors').ElementNotFoundError} ElementNotFoundError
*/
/**
* @type {$}
*/
const $ = (selectors, baseElement = document) => baseElement.querySelector(selectors);
/**
* @type {$$}
*/
const $$ = (selectors, baseElements = document) => Array.from(baseElements.querySelectorAll(selectors));
/**
* @type {lastElement}
*/
const lastElement = (selectors, baseElement = document) => {
const elements = baseElement.querySelectorAll(selectors);
return elements[elements.length - 1] || undefined;
};
/**
* @type {elementExists}
*/
const elementExists = (selectors, baseElement = document) => !!baseElement.querySelector(selectors);
/**
* @type {expectElement}
*/
const expectElement = (selectors, baseElement = document) => {
const element = baseElement.querySelector(selectors);
if (!element) throw new ElementNotFoundError(`Expected element not found: ${selectors}`);
return element;
};
/**
* @constructor
* @extends {Error}
*/
function ElementNotFoundError(message) {
this.name = 'ElementNotFoundError';
this.message = message;
this.stack = (new Error()).stack;
}
ElementNotFoundError.prototype = Object.create(Error.prototype);
ElementNotFoundError.prototype.constructor = ElementNotFoundError;
// Usage example
try {
const element = expectElement('button.submit');
console.log('Found button:', element);
} catch (error) {
if (error instanceof ElementNotFoundError) {
console.error('Button not found:', error.message);
}
}
import type { ParseSelector } from 'typed-query-selector/parser.js';
type BaseElements = ParentNode | Iterable<ParentNode>;
export function $<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected | undefined;
export function $<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElement?: ParentNode
): Selected | undefined;
export function $$<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElements?: BaseElements
): Selected[];
export function $$<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElements?: BaseElements
): Selected[];
export class ElementNotFoundError extends Error {
name: 'ElementNotFoundError';
}
export function expectElement<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected;
export function expectElement<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElement?: ParentNode
): Selected;
export function lastElement<Selector extends string, Selected extends Element = ParseSelector<Selector, HTMLElement>>(
selectors: Selector | Selector[],
baseElement?: ParentNode
): Selected | undefined;
export function lastElement<Selected extends Element = HTMLElement>(
selectors: string | string[],
baseElement?: ParentNode
): Selected | undefined;
export function elementExists(
selectors: string | string[],
baseElement?: ParentNode
): boolean;
Problem
Here's a basic type definition that's unfortunately quite wrong: