g-plane / typed-query-selector

Better typed `querySelector` and `querySelectorAll`.
https://www.npmjs.com/package/typed-query-selector
MIT License
720 stars 11 forks source link

How to use with JS with Types (JSDoc + TSC)? #42

Closed coolaj86 closed 3 weeks ago

coolaj86 commented 3 weeks ago

What's the syntax to have this import in a normal JavaScript file and have it work with JSDoc (tsc)?

What I've tried

/** @import('typed-query-selector/strict') */ // doesn't seem to update the types
/** @import type {} from 'typed-query-selector/strict' */  // E: 'from' expected.

Problem

let $input = $("input");
if (!$input) {
  throw new Error("no input selected");
}
f.value = "foo"; // E: Property 'value' does not exist on type 'Element'.

Sample Code

Here's how I'm trying to use it, in full:

/** @import('typed-query-selector/strict') */

/**
 * Select first matching element, just like console $
 * @param {String} cssSelector
 * @param {ParentNode} [$parent=document]
 */
function $(cssSelector, $parent = document) {
  let $child = $parent.querySelector(cssSelector);
  return $child;
}

/**
 * Select all matching child elements as a JS Array, just like console $$
 * @param {String} cssSelector
 * @param {ParentNode} [$parent=document]
 */
function $$(cssSelector, $parent = document) {
  let $children = $parent.querySelectorAll(cssSelector);
  let children = Array.from($children);
  return children;
}
g-plane commented 3 weeks ago

You can use tsconfig.json or jsconfig.json as the readme says.

fregante commented 3 weeks ago

Where are you trying that code? What’s your code editor?

coolaj86 commented 3 weeks ago

@fregante I'm using vim-ale, tsc, and jswt.

The project I'm working on today is just a parody project, but I use it as boilerplate for real projects: https://www.npmjs.com/package/ajquery

You can see the jsconfig and whatnot here: https://github.com/coolaj86/ajquery.js

It should work in any editor. There's no special editor-specific config.

coolaj86 commented 3 weeks ago

Copying this here from #43, since this is actually more related to this issue (documentation for how to use this as-is) than that one (request to add $ as a global export):

This is the sort of thing I would expect to be able to do:

Option A: Apply the type directly to the function:

/** @typedef {@import("typed-query-selector/strict").RelativeSelectorCallbackDefinition} RelativeSelector */
/** @typedef {@import("typed-query-selector/strict").RelativeSelectorAllCallbackDefinition} RelativeSelectorAll */

/** @type {RelativeSelector} */
const $ = (s, e = document) => e.querySelector(s)

/** @type {RelativeSelectorAll} */
const $$ = (s, e = document) => Array.from(e.querySelectorAll(s))

Option B: Apply the return type:

/** @typedef {@import("typed-query-selector/strict").AmbiElement} AmbiElement */
/** @typedef {@import("typed-query-selector/strict").AmbiElement} AmbiElement */

/**
  * @param {String} s
  * @param {ParentNode} e
  * @returns {AmbiElement}
  */
const $ = (s, e = document) => e.querySelector(s)

/**
  * @param {String} s
  * @param {ParentNode} e
  * @returns {Array<AmbiElement>}
  */
const $$ = (s, e = document) => Array.from(e.querySelectorAll(s))
fregante commented 3 weeks ago

You might want to ask StackOverflow on how to do this