{"id":13649239,"url":"https://github.com/g-plane/typed-query-selector","last_synced_at":"2025-05-14T00:07:09.953Z","repository":{"id":46028934,"uuid":"312544654","full_name":"g-plane/typed-query-selector","owner":"g-plane","description":"Better typed `querySelector` and `querySelectorAll`.","archived":false,"fork":false,"pushed_at":"2024-11-29T02:41:13.000Z","size":234,"stargazers_count":750,"open_issues_count":0,"forks_count":11,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-12T05:09:01.465Z","etag":null,"topics":["parser","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/typed-query-selector","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/g-plane.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"g-plane"}},"created_at":"2020-11-13T10:29:59.000Z","updated_at":"2025-05-05T22:04:46.000Z","dependencies_parsed_at":"2023-01-22T23:45:14.809Z","dependency_job_id":"f704d2e9-ea5a-45f5-85c1-d7b62ccd03e8","html_url":"https://github.com/g-plane/typed-query-selector","commit_stats":{"total_commits":192,"total_committers":6,"mean_commits":32.0,"dds":0.05208333333333337,"last_synced_commit":"48a5960ba59c5b6c8e9bfba5db0a6928c847308b"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g-plane%2Ftyped-query-selector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g-plane%2Ftyped-query-selector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g-plane%2Ftyped-query-selector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g-plane%2Ftyped-query-selector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/g-plane","download_url":"https://codeload.github.com/g-plane/typed-query-selector/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254043688,"owners_count":22004995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["parser","typescript"],"created_at":"2024-08-02T01:04:52.391Z","updated_at":"2025-05-14T00:07:09.932Z","avatar_url":"https://github.com/g-plane.png","language":"TypeScript","funding_links":["https://github.com/sponsors/g-plane"],"categories":["TypeScript","**1. Libraries**"],"sub_categories":["Others"],"readme":"# 🏷 Typed `querySelector`\n\n`querySelector` and `querySelectorAll` functions with better typing\nby leveraging TypeScript 4.1 template literal type.\n\n## 💿 Install\n\n```\nnpm i -D typed-query-selector\n```\n\n## 🍉 Usage\n\n### Automatic shim\n\nAll you need to do is to import this module,\nthen the `querySelector` and `querySelectorAll` function will be enhanced.\n\nThis module only works at type level and doesn't have any runtime code.\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('div#app') // ==\u003e HTMLDivElement\n\ndocument.querySelector('div#app \u003e form#login') // ==\u003e HTMLFormElement\n\ndocument.querySelectorAll('span.badge') // ==\u003e NodeListOf\u003cHTMLSpanElement\u003e\n\nanElement.querySelector('button#submit') // ==\u003e HTMLButtonElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHowirxDQDsYA6fQ5AMoVqtKAAoEGYADcAxAEMwYBAEo4AenVwAvNoB8cABIAVALIAZACIyAopXZdGzVg558iQyjWgSpcxWBwBgBm0CCy5BAA5sAcqhpaugYmFgBiYXZork4sbJxuBB7C3lAAguTkEiRg8hzcAEbyGFFo8Zo6+nAAchAYaObAJDAA8sEAPCnmAjUcma56TtTk8lBocJTwtXP5AFxGZubbjvRb9vm8hYLFohL1eDC0HLIkePUgwDBtiZ2TAEL3jyOMHoQA)_\n\nThe example above assumes you're using bundlers or build tools with transpilers,\nhowever, sometimes this may not match your situation.\nFor example, running `tsc` or Babel out of bundlers.\nIn this case, you can import this library like this:\n\n```typescript\nimport type {} from 'typed-query-selector'\n\ndocument.querySelector('div#app') // ==\u003e HTMLDivElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3gXzgMyhEOAciVQBMBaARwFcUpEKBnFAGxQGMZoiAoXshA40QKAHYwAdLXqIAym07coACiJlgANwDEAQzBgiASjgB6U3AC8lgHxwAEgBUAsgBkAIloCi7URKA)_\n\nThis looks ugly but it works.\n\nIf you aren't going to use ES Modules you can modify your `tsconfig.json`,\nhowever this is NOT recommended, unless you know what you're doing.\n\n```json\n{\n  \"compilerOptions\": {\n    \"types\": [\"typed-query-selector\"]\n  }\n}\n```\n\n### Strict mode\n\n\u003e Available in v2.3+\n\nIn strict mode, the selector parser will perform additional syntax checks on input string.\nIf there're syntax errors, return type will be `never` instead of `Element`.\n\nExample usage:\n\n```ts\nimport 'typed-query-selector/strict'\n\nconst element = document.querySelector('div[test') // return `never`\n```\n\nThis feature won't be enabled by default and you can opt-in.\nIf you want to enable this, change import entry:\n\n```diff\n- import 'typed-query-selector'\n+ import 'typed-query-selector/strict'\n```\n\nThat's all. If you pass an invalid selector,\nbecause it returns `never`, TypeScript will prevent you from\naccessing properties/methods on element or using element at somewhere.\n\nNote that it doesn't guarantee that it can detect every kind of syntax errors,\nsince such parser will become very complex and compilation performance may go bad.\n\n### Use the parser\n\nIf you just want to use the selector parser itself, we've exported for you:\n\n```typescript\nimport type {\n  ParseSelector,\n  StrictlyParseSelector, // or use the strict parser\n} from 'typed-query-selector/parser'\n\ntype MyElement = ParseSelector\u003c'form#login'\u003e\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3nACgQygZxQGUUAbFAYxmjgF84AzKCEOAciVQBMBaARwCuKKIh6FyVaAHoweQlDYAoRZzQBZRAFFyIFADt4AXmxziZStSgAeNg2ggAxKQgBzYHrYA+IA)_\n\nPlease note that you should import `typed-query-selector/parser`, not `typed-query-selector`.\nThis is safe because this import doesn't patch to the `querySelector` and `querySelectorAll` function.\n\nSometimes, you may want to specify another fallback type (such as `HTMLElement`, not default `Element` type)\nwhen failed to parse selector or failed to look up, you can pass a fallback type as the second type parameter:\n\n\u003e Available in v2.4+\n\n```ts\nimport type { ParseSelector } from 'typed-query-selector/parser'\n\ntype MyElement = ParseSelector\u003c'unknown-tag', HTMLElement\u003e // ==\u003e HTMLElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3nACgQygZxQGUUAbFAYxmjgF84AzKCEOAciVQBMBaARwCuKKIh6FyVaAHoweQlDYAoRZzQBZRAFFyIFADt4AXmxziZStSgAeNgL0BrPRADuenjBwBzNgBo4ACQAVNQAZbRRdAwA+OCkpOENDGKDQ8MiYIA)_\n\n## 💡 Supported Use Cases\n\n### With class, ID, pseudo class or attribute\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('div.container') // ==\u003e HTMLDivElement\n\ndocument.querySelector('div#app') // ==\u003e HTMLDivElement\n\ndocument.querySelector('input[name=username]') // ==\u003e HTMLInputElement\n\ndocument.querySelector('input:first-child') // ==\u003e HTMLInputElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHowirxDQDsYA6fQ5AMoVqtKAAoEGYADduVCFwCGwDoQQBKOAHotcALx6AfHAASAFQCyAGQAiMgKKV2XRs1bOefIkMo1oEqWkAYkUwMA1tXQNjc2s7aUc0D1cWNk5PAm9hP3EEFTA8GABtDkV2PTwyKFL2AF0InX0jU0srAEkOAphE5KZUj15MwWzRCXzCgC4AM2AoEhgsKgALYHIMBqjm2PbOwp70oA)_\n\nEven mix them:\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('input.form-control[name=username]') // ==\u003e HTMLInputElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHowirxDQDsYA6fQ5AMoVqtKAAoEwDmDw8AZtBBYqELlAjkA2hwCG7ALx4yUXewC6CAJRwA9Dbj79APjgAJACoBZADIBJabIAopTsXEA)_\n\nAnd with `:is()` or `:where()`:\n\n\u003e Available in v2.5+\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector(':is(div#id, span.class[k=v])') // ==\u003e HTMLDivElement | HTMLSpanElement\n\ndocument.querySelector(':where(div#id, span.class[k=v])') // ==\u003e HTMLDivElement | HTMLSpanElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHowirxDQDsYA6fQ5AMoVqtKAAoEALmAkxGYADcAxMAwAaOCTABDDtyrltJEgG0A1gF4FAXQCUCW3AD0TuBYsA+OAAkAKgFkAGQARRQBRSnYuOAAfHwDAgR0OCLQomEZmVnTeAiIhShpoCUkAdwALQjQ5RRV1TWT9Q2NzKzsHZ1d3Lz8g0IVU9Nj4oKTdQc4YIA)_\n\n### Combinators\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('body div') // ==\u003e HTMLDivElement\n\ndocument.querySelector('body \u003e form') // ==\u003e HTMLFormElement\n\ndocument.querySelector('h1 + p') // ==\u003e HTMLParagraphElement\n\ndocument.querySelector('h2 ~ p') // ==\u003e HTMLParagraphElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHowirxDQDsYA6fQ5AMoVqtKAAoEAIwgZkcDMABuCAJRwA9OrgBebQD44ACQAqAWQAyAESUBRSuy6NmrBzz5EhlGtAnTZcAwAzaBBVDS1dAxMLADEQuzRXJxY2TjcCD2FvcQQACwBGOABqODAwzR19IzNzAAUAQyh6gHMmsFyEpKYU114MwSzRCVyAJjgAP1LyiKrousaWto77NKA)_\n\n### Grouping selectors\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('div, span') // ==\u003e HTMLDivElement | HTMLSpanElement\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHowirxDQDsYA6fQ5AMoVqtKAAoEGYADcANHBJgAhhwQBKOAHpNcALy6AfHAASAFQCyAGQAiMgKKV2XOAB8TFywOUcHaJzCA)_\n\n### Fallback\n\n#### Custom Elements\n\nIf you passed an unknown tag, it will fall back to `Element`.\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('my-web-component') // ==\u003e Element\n```\n\nHowever, you can override it by specifying a concrete type as a type argument.\n\n```typescript\ndocument.querySelector\u003cMyComponent\u003e('my-web-component') // ==\u003e MyComponent\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHo2vIEMo04q2SS4BZZAGEI4CADs04+GgAeMKRj4AJACr8AMgFFKIKfADeAX0YYIVPHukA6fIWQBlCtVpQAFAhDEA7mgBGWFSikJLSCACUcAD0UXAAvHEAfHA6aFYwpuaW+rYERE6UNNAAPIIiYqEwiR5eWL4BQRX6EdGxCcllwRL6QA)_\n\nAlternatively, you can use [global augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation) and [interface merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces) to extend `HTMLElementTagNameMap` with your custom elements.\n\n```typescript\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'my-web-component': MyComponent\n  }\n}\n\ndocument.querySelector('my-web-component') // ==\u003e MyComponent\n```\n\n_[Playground](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAchgTzAUwCYFoCOBXNKZLAZzQBs0BjGaBAKHo2vIEMo04q2SS4BZZAGEI4CADs04+GgAeMKRj4AJACr8AMgFFKIKfADeAX0bNu7TgHNyEAEatycA-Tiu4waYQBmrKpzWaOmh60qqslgByrHr8rGBOLm5JCCDEAO5otlhUopCS0ggAXALCuRL6ANyJriYmTBBUeCEwAHT4hMgAyhTUtFAAFCnpmdll+TAIAJRwAPQzcAC8CwB8JSJi40A)_\n\n#### Invalid selector\n\nWhen passing an invalid selector which causes parsing error,\nit will fall back to `Element`.\n\n```typescript\nimport 'typed-query-selector'\n\ndocument.querySelector('div#app \u003e') // ==\u003e Element\n\ndocument.querySelector('div#app ?') // ==\u003e Element\n```\n\nHowever, if you're using strict mode,\nall `querySelector` calls above will return `never` type.\nThis can stop you from misusing it.\n\n```ts\nimport 'typed-query-selector/strict'\n\nconst el = document.querySelector('div#app \u003e')\nel.className // TypeScript will report error when compiling\n```\n\n## 🔩 Technical Details\n\n### Why returns `never` in strict mode?\n\nIn runtime, if you pass an invalid selector string to `querySelector` or\n`querySelectorAll` function, it will throw an error instead of returning\n`null` or `undefined` or anything else.\nFor details, please read [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type).\n\n## 🔗 Related\n\n- [Type Gymnastics](https://github.com/g-plane/type-gymnastics) - Collection of wonderful TypeScript type gymnastics code snippets.\n\n## 📃 License\n\nMIT License\n\nCopyright (c) 2020-present Pig Fang\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg-plane%2Ftyped-query-selector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fg-plane%2Ftyped-query-selector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg-plane%2Ftyped-query-selector/lists"}