{"id":25426793,"url":"https://github.com/kamranayub/ts-has-guards","last_synced_at":"2026-04-27T20:31:37.493Z","repository":{"id":277629016,"uuid":"932839757","full_name":"kamranayub/ts-has-guards","owner":"kamranayub","description":"TypeScript utility types that augment built-in collection types like Map, Set, FormData, and URLSearchParams to offer type guarding capability to getters/setters","archived":false,"fork":false,"pushed_at":"2025-02-18T04:08:30.000Z","size":24,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-14T05:23:59.031Z","etag":null,"topics":["deno","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kamranayub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2025-02-14T16:06:08.000Z","updated_at":"2025-02-21T18:41:41.000Z","dependencies_parsed_at":"2025-02-15T03:28:17.809Z","dependency_job_id":null,"html_url":"https://github.com/kamranayub/ts-has-guards","commit_stats":null,"previous_names":["kamranayub/ts-has-guards"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kamranayub/ts-has-guards","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamranayub%2Fts-has-guards","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamranayub%2Fts-has-guards/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamranayub%2Fts-has-guards/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamranayub%2Fts-has-guards/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kamranayub","download_url":"https://codeload.github.com/kamranayub/ts-has-guards/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamranayub%2Fts-has-guards/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32354564,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T20:07:02.737Z","status":"ssl_error","status_checked_at":"2026-04-27T20:07:00.910Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["deno","typescript"],"created_at":"2025-02-17T00:22:09.959Z","updated_at":"2026-04-27T20:31:37.467Z","avatar_url":"https://github.com/kamranayub.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ts-has-guards\n\n[![JSR](https://jsr.io/badges/@kamranayub/ts-has-guards)](https://jsr.io/@kamranayub/ts-has-guards)\n\nThis package provides type-guarded versions of the `has` method for built-in\ntypes like `Map`, `FormData`, and `URLSearchParams` so that you can narrow\n`.get(key)` return type within the conditional type guard blocks.\n\n\u003e [!WARNING]\n\u003e This package is pretty experimental, but I welcome improvements to the DX.\n\n## Why use this package?\n\nIf you've ever tried to call `get(key)` after calling `has(key)` and lamented\nthe fact it still returns `| undefined` or `| null`, you know this problem well.\n\nFor example, this will throw an error in vanilla TS:\n\n```ts\nconst map = new Map([[\"key\", 1]] as const);\n\nif (map.has(\"key\")) {\n  const value: number = map.get(\"key\");\n  //  !!!   ^---- ERROR!\n}\n```\n\nBut with this library, the type guard works like you might expect.\n`map.get('key')` will be narrowed to `number` instead of `number | undefined`.\n\nThis library provides type-guarded `has` methods for:\n\n- `Map.has` using `GuardedMap`\n- `FormData.has` using `GuardedFormData`\n- `URLSearchParams.has` using `GuardedURLSearchParams`\n\n## Getting Started\n\nChoose your poison:\n\n```\ndeno add jsr:@kamranayub/ts-has-guards\n\nnpx jsr add @kamranayub/ts-has-guards\nyarn dlx jsr add @kamranayub/ts-has-guards\npnpm dlx jsr add @kamranayub/ts-has-guards\nbunx jsr add @kamranayub/ts-has-guards\n```\n\nThis library was built with [Deno](https://deno.com).\n\n## Usage\n\nTo use the typed versions of `Map`, `URLSearchParams` and `FormData`, you need\nto explicitly use and import them (each of them are prefixed with `Guarded`):\n\n```ts\nimport {\n  GuardedFormData,\n  GuardedMap,\n  GuardedURLSearchParams,\n} from \"@kamranayub/ts-has-guards\";\n\n// Use like regular API but you can pass an explicit set of known keys\ntype KnownKeys = \"key1\" | \"key2\";\n\nconst map = new GuardedMap\u003cKnownKeys, number\u003e();\nconst searchParams = new GuardedURLSearchParams\u003cKnownKeys\u003e();\nconst formData = new GuardedFormData\u003cKnownKeys\u003e();\n```\n\nWhen converting built-in lib types to the guarded versions, you must cast as\n`unknown` first:\n\n```ts\nmap as unknown as GuardedMap\u003cMyKeys, string\u003e;\nformData as unknown as GuardedFormData\u003cMyKeys\u003e;\nsearchParams as unknown as TypedSearchParams\u003cMyKeys\u003e;\n```\n\nYou can reference the tests or docs for some more examples.\n\n## Docs\n\nView the [docs on JSR](https://jsr.io/@kamranayub/ts-has-guards/doc).\n\n## Shameless Plug\n\nMaybe have a listen to [typescript.fm](https://typescript.fm). :microphone:\n\n## FAQ\n\n\u003cdetails\u003e\n    \u003csummary\u003eWhy can't I augment the global types?\u003c/summary\u003e\n\nYou could with `Map`, however this is not supported for a published JSR package\n[due to slow typings](https://jsr.io/docs/about-slow-types#global-augmentation).\nIf you'd like to use a local version in your app, you can copy from\n[the StackOverflow answer](https://stackoverflow.com/a/73467859/109458) and put\nit under a `globals.d.ts` file or `declare global { }` if using modules.\n\nThis will not work with the `FormData` and `URLSearchParams` though because\nthose types are not generic and TS will yell at you if you try to redeclare them\nwith generic typings.\n\n\u003c/details\u003e\n\n## Credits\n\nBuilt on the [shoulders of giants](https://stackoverflow.com/a/73467859/109458).\n\nInspired by\n[@dbushell](https://bsky.app/profile/dbushell.com/post/3li5bohbiok27).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamranayub%2Fts-has-guards","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkamranayub%2Fts-has-guards","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamranayub%2Fts-has-guards/lists"}