Skip to content

๐Ÿช„ A TypeScript-types patch for querySelector/querySelectorAll, make them return types you expect them to! ๐Ÿ”ฎ

License

Notifications You must be signed in to change notification settings

igorskyflyer/npm-magic-queryselector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Icon of Magic querySelector

Magic querySelector


๐Ÿช„ A TypeScript-types patch for querySelector() / querySelectorAll(), make them return types you expect them to! ๐Ÿ”ฎ



๐Ÿ“ƒ Table of Contents



๐Ÿค– Features

  • ๐Ÿง  Smart IntelliSense - autoโ€‘suggests valid CSS selectors and infers exact element types
  • ๐Ÿ“Œ Works with literal selector strings to power IntelliSense
  • ๐Ÿช„ Typeโ€‘driven safety - catches invalid selectors at compile time in TypeScript
  • ๐Ÿท Tag name mapping - resolves HTML tag names to their correct HTMLElement types
  • ๐ŸŽฏ Selector parsing - supports tag, class, ID, and attribute selectors in type space
  • ๐Ÿ”— Combinator awareness - understands descendant, child, sibling, and column combinators
  • ๐ŸŒฑ Pseudoโ€‘class support - recognizes :root and maps it to the <html> element type
  • ๐Ÿ“œ Global augmentation - extends Document and Element to return precise types for querySelector/querySelectorAll
  • โšก Zero runtime cost - all logic is purely in TypeScript types, no JS overhead


๐Ÿ•ต๐Ÿผ Usage

Install it by executing any of the following, depending on your preferred package manager:

pnpm add @igorskyflyer/magic-queryselector
yarn add @igorskyflyer/magic-queryselector
npm i @igorskyflyer/magic-queryselector


Here's magic-querySelector in action.


without-magic.mp4
Without magic-queryselector


with-magic.mp4
With magic-queryselector


Visual Studio Code theme used in the demonstration is Kai ๐ŸŒŠ An external link.

Including the magic-queryselector into your project depends on the language of it. Please see the appropriate section for your project:


TypeScript

If you want to use it with TypeScript, you need to import this module. This augments the global Document and Element interfaces so querySelector() and querySelectorAll() return the correct element type based on your selector.

To do so, copy the following code:

import '@igorskyflyer/magic-queryselector'

and then do one of the either options:


[ 1st option ]

Create a d.ts file (recommended)


โš ๏ธ WARNING

This method requires a valid tsconfig.json file to be present in the root of your project.


Create a magic.d.ts file in the root directory of your project and add the snippet you copied:


magic.d.ts

import '@igorskyflyer/magic-queryselector'

That's it! You're all set up. ๐Ÿฅณ


๐Ÿ’ก TIP

Language server

TypeScript's language server sometimes likes to play games, if the patch doesn't work immediately please restart TypeScript language server or Visual Studio Code.



[ 2nd option ]

Add to the entrypoint

Add the code snippet you copied to the top of your entrypoint/main TypeScript file.


index.ts

import '@igorskyflyer/magic-queryselector'

๐Ÿ’ก TIP

Language server

TypeScript's language server sometimes likes to play games, if the patch doesn't work immediately please restart TypeScript language server or Visual Studio Code.


JavaScript


โ„น๏ธ NOTE

Easy install

If you want to use it with JavaScript, you don't need to do anything besides installing the package.


๐Ÿ’ก TIP

Language server

TypeScript's language server sometimes likes to play games, if the patch doesn't work immediately please restart TypeScript language server or Visual Studio Code.



๐Ÿคน๐Ÿผ API

This patch extends the default (return) type inference of TypeScript by inferring the types from the input string containing selectors/combinators passed to querySelector() / querySelectorAll().


โ„น๏ธ NOTE

API behavior

querySelector() will return the type listed in the table below, e.g. HTMLDivElement, while querySelectorAll() will return NodeListOf<T> of the same type, e.g. NodeListOf<HTMLDivElement>.

Unsupported or unrecognised selectors will gracefully fall back to the generic HTMLElement type, ensuring your code still typeโ€‘checks while signalling that no specific element type could be inferred.

For brevity this table only shows the types for querySelector().

Read more about selector structure External link and selectors and combinators External link on MDN.


The following table shows which selectors/combinators are supported along with the inferred return types for the given examples.


Implementation table
Selector/Combinator Example Compatibility Inference Before/After
Type + ID div#app โœ… Patched Element/HTMLDivElement
Type + Class a.myLink โœ… Patched Element/HTMLAnchorElement
Type + Attribute a[title] โœ… Patched Element/HTMLAnchorElement
Descendant div video โœ… Patched Element/HTMLVideoElement
Child main > a โœ… Patched Element/HTMLAnchorElement
Next-sibling div + span โœ… Patched Element/HTMLSpanElement
Subsequent-sibling h1 ~ pre โœ… Patched Element/HTMLPreElement
Pseudo-class :root :root โœ… Patched Element/HTMLHtmlElement
Column (1) col || td โœ… Patched Element/HTMLTableCellElement
Type li โ€” Native HTMLLIElement/HTMLLIElement
ID #share โ€” Native Element/Element
Class .footer โ€” Native Element/Element
Attribute [title] โ€” Native Element/Element
Universal * โ€” Native Element/Element
Unresolved <any> โ€” Native Element/Element
Table 1. implementation table


(1) The column combinator is a highly-experimental upcoming combinator "that is placed between two CSS selectors. It matches only those elements matched by the second selector that belong to the column elements matched by the first." (source: MDN An external link)



๐Ÿ—’๏ธ Examples

main.js

const video = document.querySelector('div#app > video') // HTMLVideoElement | null
const audios = document.querySelectorAll('div#app > audio') // NodeListOf<HTMLAudioElement>

if(video) {
  video.src = '<some_URL>' // now we can access all <video> properties and methods
}

if(audios.length > 0) {
  audios[0].src = '<some_URL>' // ๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€
}


๐Ÿ“ Changelog

๐Ÿ“‘ The changelog is available here, CHANGELOG.md.



๐Ÿชช License

Licensed under the MIT license which is available here, MIT license.



๐Ÿ’– Support

I work hard for every project, including this one and your support means a lot to me!
Consider buying me a coffee. โ˜•

Donate to igorskyflyer

Thank you for supporting my efforts! ๐Ÿ™๐Ÿ˜Š


๐Ÿงฌ Related

@igorskyflyer/jmap

๐Ÿ•ถ๏ธ Reads a JSON file into a Map. ๐ŸŒป


@igorskyflyer/extendable-string

๐Ÿฆ€ ExtendableString allows you to create strings on steroids that have custom transformations applied to them, unlike common, plain strings.. ๐Ÿช€


@igorskyflyer/unc-path

๐Ÿฅฝ Provides ways of parsing UNC paths and checking whether they are valid. ๐ŸŽฑ


@igorskyflyer/duoscribi

โœ’ DรบรถScrรญbรฎ allows you to convert letters with diacritics to regular letters. ๐Ÿค“


@igorskyflyer/clone

๐Ÿงฌ A lightweight JavaScript utility allowing deep copy-by-value of nested objects, arrays and arrays of objects. ๐Ÿช




๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Author

Created by Igor Dimitrijeviฤ‡ (@igorskyflyer).

Sponsor this project