{"id":17920884,"url":"https://github.com/eth-p/unnarrowed-ts","last_synced_at":"2025-07-18T18:34:36.454Z","repository":{"id":236677210,"uuid":"792899817","full_name":"eth-p/unnarrowed-ts","owner":"eth-p","description":"A type-only TypeScript library for detecting unnarrowed types and asserting narrowing of generic types.","archived":false,"fork":false,"pushed_at":"2024-04-28T02:19:41.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-09T03:08:44.091Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/eth-p.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":"2024-04-27T21:39:51.000Z","updated_at":"2024-04-28T02:19:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"48813714-d681-4383-b4bd-cb4de4ca58d8","html_url":"https://github.com/eth-p/unnarrowed-ts","commit_stats":null,"previous_names":["eth-p/unnarrowed-ts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eth-p/unnarrowed-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eth-p%2Funnarrowed-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eth-p%2Funnarrowed-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eth-p%2Funnarrowed-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eth-p%2Funnarrowed-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eth-p","download_url":"https://codeload.github.com/eth-p/unnarrowed-ts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eth-p%2Funnarrowed-ts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265810182,"owners_count":23831946,"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":[],"created_at":"2024-10-28T20:29:30.253Z","updated_at":"2025-07-18T18:34:36.433Z","avatar_url":"https://github.com/eth-p.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# narrowable\n\nA type-only TypeScript library for detecting unnarrowed types and asserting narrowing of generic types.\n\n## What can I do with this?\n\n- **[Associated types.](./examples/associated-types.ts)**\n- **[Type narrowing assertions.](./examples/asserted-narrow.ts)**\n- [Detecting when `infer T` uses the `extends` type as a fallback.](./examples/infer-fallback.ts)\n\n## Types\n\n### Unnarrowed\n\nA type that has not been narrowed yet.\n\n```ts\ntype Unnarrowed\u003cT\u003e\n```\n\n**Usage:**\n\n```ts\ninterface AssociatedTypes {\n    DateType: Unnarrowed\u003cDate | number | string\u003e\n}\n```\n\n### NarrowedFrom\n\nThe narrowed form of an [`Unnarrowed`](#unnarrowed) type.\n\nIf used on the right-hand side of an `extends` statement such as\n`MyClass\u003cU extends NarrowedFrom\u003cT\u003e\u003e` where `T` is `Unnarrowed`, it will cause an\nerror when `U = T`.\n\n```ts\ntype NarrowedFrom\u003cT\u003e\n```\n\n**Behavior:**\n\n  * If `T` is `Unnarrowed\u003cU\u003e`, returns `U`.\n  * If `T` is an object with `Unnarrowed\u003cU\u003e` properties, the `Unnarrowed` is stripped from them.\n  * Otherwise, returns an *error type*.\n\n**Usage:**\n\n```ts\ntype DateType = Unnarrowed\u003cDate | number | string\u003e\ntype DateGetter\u003cT extends NarrowedFrom\u003cDateType\u003e = NarrowedFrom\u003cDateType\u003e\u003e = () =\u003e T;\n//                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \u003c-- assert narrowing\n\n/** Defined elsewhere */\ndeclare function getPublishDate(package: string): DateType;\n\n/**\n * Prints a date returned by a DateGetter.\n */\nfunction printDateFrom\u003cF extends DateGetter\u003e(getter: F) {\n    console.log(getter());\n}\n\nprintDateFrom(() =\u003e new Date()); // ok\nprintDateFrom(() =\u003e getPublishDate(\"unnarrowed\"));\n//                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \u003c-- error, it returns unnarrowed DateType\n```\n\n### AssertNarrowed\n\nAsserts that the given type has been narrowed from an `Unnarrowed\u003cU\u003e`.\n\n```ts\ntype AssertNarrowed\u003cT, Options = {}\u003e\n```\n\n**Options:**\n\n```ts\n{\n\n    // If set to `true`, the assertion will only pass if the type is\n    // narrowed to a single, non-union type.\n    strict?: true | false\n    \n    // If set, this type will be returned when the assertion fails.\n    failType: any;\n\n}\n```\n\n**Usage:**\n\n```ts\ntype GlasswareMaterial = Unnarrowed\u003c'glass' | 'crystal'\u003e;\ninterface Glassware\u003cT extends GlasswareMaterial\u003e {\n    type: AssertNarrowed\u003cT, {\n        strict: true,\n        failType: never,\n    }\u003e\n}\nconst aWineGlass: Glassware\u003c'glass' | 'crystal'\u003e = {\n    type: \"glass\"\n//  ~~~~ \u003c-- T is not strictly narrowed, so `type` is never\n}\n```\n\n### AssertStrictlyNarrowed\n\nAn alias for [`AssertNarrowed`](#assertnarrowed) with the `strict` option set to `true`.\n\n```ts\ntype AssertStrictlyNarrowed\u003cT, Options = {}\u003e\n```\n\n## Utility Types\n\n### IsUnnarrowed\n\nChecks if a type is [`Unarrowed\u003cT\u003e`](#unnarrowed).\n\nIf the given type is `any`, an *error type* will be returned.\n\n```ts\ntype IsUnnarrowed\u003cT, WhenTrue=true, WhenFalse=false, WhenError=/* error */\u003e\n```\n\n**Usage:**\n\n```ts\ntype should_be_true  = IsUnnarrowed\u003cUnnarrowed\u003cstring\u003e\u003e;\ntype should_be_false = IsUnnarrowed\u003cstring\u003e;\ntype is_error        = IsUnnarrowed\u003cany\u003e;\n```\n\n### IsNarrowed\n\nChecks if a type is not [`Unarrowed\u003cT\u003e`](#unnarrowed).\n\nIf the given type is `any`, the `WhenTrue` type will be returned.\n\n```ts\ntype IsUnnarrowed\u003cT, WhenTrue=true, WhenFalse=false, WhenError=WhenTrue\u003e\n```\n\n**Usage:**\n\n```ts\ntype should_be_true  = IsNarrowed\u003cstring\u003e;\ntype should_be_false = IsNarrowed\u003cUnnarrowed\u003cstring\u003e\u003e;\ntype also_true       = IsNarrowed\u003cany\u003e;\n```\n\n### IsStrictlyNarrowed\n\nChecks if a type is not [`Unarrowed\u003cT\u003e`](#unnarrowed), and is not a type union.\n\nIf the given type is `any`, the `WhenFalse` type will be returned.\n\n```ts\ntype IsUnnarrowed\u003cT, WhenTrue=true, WhenFalse=false, WhenError=WhenTrue\u003e\n```\n\n**Usage:**\n\n```ts\ntype should_be_true  = IsStrictlyNarrowed\u003cstring\u003e;\ntype should_be_false = IsStrictlyNarrowed\u003cUnnarrowed\u003cstring\u003e\u003e;\ntype also_false_1    = IsStrictlyNarrowed\u003cstring | boolean\u003e;\ntype also_false_2    = IsStrictlyNarrowed\u003cany\u003e;\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feth-p%2Funnarrowed-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feth-p%2Funnarrowed-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feth-p%2Funnarrowed-ts/lists"}