{"id":16691334,"url":"https://github.com/dphilipson/typescript-string-enums","last_synced_at":"2025-08-23T04:10:08.644Z","repository":{"id":57383951,"uuid":"79528555","full_name":"dphilipson/typescript-string-enums","owner":"dphilipson","description":"Typesafe string enums in TypeScript pre-2.4.","archived":false,"fork":false,"pushed_at":"2019-02-27T01:07:03.000Z","size":63,"stargazers_count":82,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-09T17:59:25.279Z","etag":null,"topics":["enum","typescript"],"latest_commit_sha":null,"homepage":"","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/dphilipson.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}},"created_at":"2017-01-20T05:31:46.000Z","updated_at":"2025-03-23T23:42:01.000Z","dependencies_parsed_at":"2022-09-14T00:52:31.926Z","dependency_job_id":null,"html_url":"https://github.com/dphilipson/typescript-string-enums","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/dphilipson/typescript-string-enums","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphilipson%2Ftypescript-string-enums","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphilipson%2Ftypescript-string-enums/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphilipson%2Ftypescript-string-enums/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphilipson%2Ftypescript-string-enums/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dphilipson","download_url":"https://codeload.github.com/dphilipson/typescript-string-enums/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphilipson%2Ftypescript-string-enums/sbom","scorecard":{"id":354357,"data":{"date":"2025-08-11","repo":{"name":"github.com/dphilipson/typescript-string-enums","commit":"c15feb74924d342d178d67598474f2b6cad346fc"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/24 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"74 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-832h-xg76-4gv6","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-9vvw-cc9w-f27h","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-hr2v-3952-633q","Warn: Project is vulnerable to: GHSA-h6ch-v84p-w6p9","Warn: Project is vulnerable to: GHSA-ff7x-qrg7-qggm","Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-q42p-pg8m-cqh6","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq","Warn: Project is vulnerable to: GHSA-jp4x-w63m-7wgm","Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-4hpf-3wq7-5rpr","Warn: Project is vulnerable to: GHSA-f522-ffg8-j8r6","Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-282f-qqgm-c34q","Warn: Project is vulnerable to: GHSA-fvqr-27wr-82fm","Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574","Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-7px7-7xjx-hxm8","Warn: Project is vulnerable to: GHSA-x5pg-88wf-qq4p","Warn: Project is vulnerable to: GHSA-p9wx-2529-fp83","Warn: Project is vulnerable to: GHSA-5v2h-r2cx-5xgj","Warn: Project is vulnerable to: GHSA-rrrm-qjm4-v8hf","Warn: Project is vulnerable to: GHSA-f9cm-qmx5-m98h","Warn: Project is vulnerable to: GHSA-7wpw-2hjm-89gp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-w9mr-4mfr-499f","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-6394-6h9h-cfjg","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-gqgv-6jq5-jjj9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-2m39-62fm-q8r3","Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-g7q5-pjjr-gqvp","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-xc7v-wxcw-j472","Warn: Project is vulnerable to: GHSA-v2p6-4mp7-3r9v","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T09:10:41.385Z","repository_id":57383951,"created_at":"2025-08-18T09:10:41.385Z","updated_at":"2025-08-18T09:10:41.385Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271495184,"owners_count":24769518,"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","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["enum","typescript"],"created_at":"2024-10-12T16:07:55.339Z","updated_at":"2025-08-23T04:10:08.617Z","avatar_url":"https://github.com/dphilipson.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TypeScript String Enums\n\nTypesafe string enums in TypeScript pre-2.4.\n\n[![Build\nStatus](https://travis-ci.org/dphilipson/typescript-string-enums.svg?branch=master)](https://travis-ci.org/dphilipson/typescript-string-enums)\n\n**As of TypeScript 2.4, this library is made mostly obsolete by native string\nenums** (see the\n[announcement](https://blogs.msdn.microsoft.com/typescript/2017/06/27/announcing-typescript-2-4/)).\nI recommend that most users who are on at least TypeScript 2.4 now use native\nenums instead. There are still a few minor reasons to continue to use this\nlibrary, as discussed in the [Advantages over native string\nenums](#advantages-over-native-string-enums) section.\n\n## Table of Contents\n\n* [Installation](#installation)\n* [Usage](#usage)\n  - [Creating and using enums](#creating-and-using-enums)\n  - [Additional functions](#additional-functions)\n    - [Enum.isType(enum, value)](#enumistypeenum-value)\n    - [Enum.keys(enum)](#enumkeysenum)\n    - [Enum.values(enum)](#enumvaluesenum)\n    - [Enum.ofKeys(object)](#enumofkeysobject)\n* [Motivation](#motivation)\n  - [Why not built-in enums?](#why-not-built-in-enums)\n  - [Why not string literals?](#why-not-string-literals)\n* [How It Works](#how-it-works)\n* [Advantages over native string enums](#advantages-over-native-string-enums)\n* [Acknowledgements](#acknowledgements)\n\n## Installation\n\n```\nnpm install --save typescript-string-enums\n```\n\nThis library requires TypeScript 2.2 or later. If you require TypeScript 2.1\ncompatibility, version 0.2.0 of this library is the last one with support.\n\n## Usage\n\n### Creating and using enums\n\nDefine an enum as follows:\n\n``` javascript\n// Status.ts\nimport { Enum } from \"typescript-string-enums\";\n\nexport const Status = Enum(\"RUNNING\", \"STOPPED\");\nexport type Status = Enum\u003ctypeof Status\u003e;\n```\n\nUse it elsewhere:\n\n``` javascript\nimport { Status } from \"./Status\";\n\nconsole.log(Status.RUNNING); // -\u003e \"RUNNING\";\n\n// Works fine.\nconst goodStatus: Status = Status.RUNNING;\n\n // TypeScript error: Type '\"hello\"' is not assignable to type '\"RUNNING\" | \"STOPPED\"'\nconst badStatus: Status = \"hello\";\n\n// Enum can be used for discriminated unions:\n\ntype State = RunningState | StoppedState;\n\ninterface RunningState {\n    status: typeof Status.RUNNING;\n    pid: number;\n}\n\ninterface StoppedState {\n    status: typeof Status.STOPPED;\n    shutdownTime: Date;\n}\n\nfunction saySomethingAboutState(state: State) {\n    // The following typechecks.\n    if (state.status === Status.RUNNING) {\n        console.log(\"The pid is \" + state.pid);\n    } else if (state.status === Status.STOPPED) {\n        console.log(\"The shutdown time is \" + state.shutdownTime);\n    }\n}\n```\n\nInstead of a list of values, an object may be passed instead if it is desired\nthat the string values be different from the constant names. This also has the\nadvantage of allowing JSDoc comments to be specified on individual values. For\nexample:\n\n``` javascript\nexport const Status = Enum({\n    /**\n     * Hovering over Status.RUNNING in an IDE will show this comment.\n     */\n    RUNNING: \"running\",\n    STOPPED: \"stopped\",\n});\nexport type Status = Enum\u003ctypeof Status\u003e;\n\nconsole.log(Status.RUNNING); // -\u003e \"running\"\n```\n\n### Additional functions\n\n#### `Enum.isType(enum, value)`\n\n`Enum.isType` checks if a value is of a given enum type and can be used as a\ntype guard. For example:\n\n``` javascript\nconst Color = Enum(\"BLACK\", \"WHITE\");\ntype Color = Enum\u003ctypeof Color\u003e;\n\nlet selectedColor: Color;\nconst colorString = getUserInputString(); // Unsanitized string.\n\n// TypeScript error: Type 'string' is not assignable to type '\"BLACK\" | \"WHITE\"'.\nselectedColor = colorString;\n\nif (Enum.isType(Color, colorString)) {\n    // No error this time because within type guard.\n    selectedColor = colorString;\n} else {\n    throw new Error(`${colorString} is not a valid color`);\n}\n```\n\n#### `Enum.keys(enum)`\n\nResembles `Object.keys()`, but provides strict typing in its return type.\n\n#### `Enum.values(enum)`\n\nResembles `Object.values()`, but provides strict typing in its return type.\n\nExample of both `Enum.keys()` and `Enum.values()`:\n\n``` javascript\nconst FileType = Enum({\n    PDF: \"application/pdf\",\n    Text: \"text/plain\",\n    JPEG: \"image/jpeg\",\n});\ntype FileType = Enum\u003ctypeof FileType\u003e;\n\nconst keys = Enum.keys(FileType);\n// Inferred type: (\"PDF\" | \"Text\" | \"JPEG\")[]\n// Return value: [\"PDF\", \"Text\", \"JPEG\"] (not necessarily in that order)\n\nconst values = Enum.values(FileType);\n// Inferred type: (\"application/pdf\" | \"text/plain\" | \"image/jpeg\")[]\n// Return value: [\"application/pdf\", \"text/plain\", \"image/jpeg\"] (not necessarily in that order)\n```\n\n#### Enum.ofKeys(object)\n\nCreates a new enum with the same keys as the provided enum or object and whose\nvalues are equal to its keys. This is most useful if for some reason it is\nnecessary to do string comparisons against the keys of an enum rather than the\nvalues. For example:\n\n``` javascript\nconst ErrorColor = Enum({ OK: \"green\", ERROR: \"red\" });\ntype ErrorColor = Enum\u003ctypeof ErrorColor\u003e;\n\nconst ErrorLevel = Enum.ofKeys(ErrorColor);\n\nconst errorLevel = getErrorLevel();\n\nif (errorLevel === ErrorLevel.ERROR) {\n    ...\n}\n```\n\n## Motivation\n\nEnums are useful for cleanly specifying a type that can take one of a few\nspecific values. TypeScript users typically implement enums in one of two ways:\nbuilt-in [TypeScript\nenums](https://www.typescriptlang.org/docs/handbook/enums.html) or string\nliterals, but each of these has drawbacks.\n\n### Why not built-in enums?\n\nBuilt-in enums have one big drawback. Their runtime value is a number, which is\nannoying during development and makes them unsuitable for use with external\nAPIs.\n\n``` javascript\nenum Status {\n    RUNNING, STOPPED\n}\n\nconst state = { status: Status.RUNNING, pid: 12345 };\nconsole.log(state);\n// -\u003e { status: 0, pid: 12345 }. What status was that again?\n// I hope you're not expecting other services to send you objects that look like this.\n```\n\n### Why not string literals?\n\nString literals make refactoring difficult. Suppose I have two enums:\n\n``` javascript\ntype Status = \"RUNNING\" | \"STOPPED\";\ntype TriathlonStage = \"SWIMMING\" | \"CYCLING\" | \"RUNNING\";\n```\n\nThen if at a later stage I want to change `Status` to be `\"STARTED\" |\n\"STOPPED\"`, there's no easy way to do it. I can't globally find/replace\n`\"RUNNING\"` to `\"STARTED\"` because it will also change the unrelated string\nconstants representing `TriathlonStage`. Instead, I have to examine every\noccurrance of the string `\"RUNNING\"` to see if it needs to change. Besides,\nthese kinds of global non-semantic substitutions should make you nervous.\n\nAnother disadvantage of string literals comes when using IDE autocomplete\nfeatures. It's convenient to be able to type `Status.` and have autocomplete\nsuggest `Status.RUNNING` and `Status.STOPPED`, but with string literals no such\nsuggestion is possible.\n\nI might try to solve both problems by introducing constants for the string\nliterals, but this has issues as well:\n\n``` javascript\n// Typo on \"STOPPED\" not caught by anything below without additional boilerplate.\ntype Status = \"RUNNING\" | \"STPOPED\";\n\n// Naive attempts to define constants for these don't work, as shown below.\nconst StatusNaive = {\n    RUNNING: \"RUNNING\",\n    STOPPED: \"STOPPED\",\n};\n\n// Type error even though it shouldn't be, because StatusNaive.RUNNING has type\n// string which is not assignable to Status.\nconst status: Status = StatusNaive.RUNNING;\n\n// Correctly defining constants is annoyingly repetitive. I shouldn't need to\n// write each value three times.\nconst Status = {\n    RUNNING: \"RUNNING\" as \"RUNNING\",\n    STOPPED: \"STOPPED\" as \"STOPPED\",\n};\n```\n\nThis library is effectively a programmatic version of these repetitive\ndefinitions. It attempts to provide the best of both worlds: string enums with\nthe convenience of built-in enums.\n\n## How It Works\n\nThis section is not necessary to use this library, but for those curious about\nhow it is implemented, read on. The explanation uses the concepts of index types\nand mapped types, as described in TypeScript's [Advanced\nTypes](https://www.typescriptlang.org/docs/handbook/advanced-types.html) page.\n\nThe relevant type declarations are as follows:\n\n``` javascript\nfunction Enum\u003cV extends string\u003e(...values: V[]): { [K in V]: K };\nfunction Enum\u003c\n    T extends { [_: string]: V },\n    V extends string\n\u003e(definition: T): T;\n\n...\n\ntype Enum\u003cT\u003e = T[keyof T];\n```\n\nWe are creating a overloaded function named `Enum` and a type named `Enum`, so\nboth can be imported with a single symbol.\n\nConsider the first overload, which handles the case of variadic arguments\nrepresenting the enum values. In TypeScript, a string constant is a type (for\nexample, in `const foo = \"Hello\"`, the variable `foo` is assigned type\n`\"Hello\"`). This means that the array\n\n``` javascript\n[\"RUNNING\", \"STOPPED\"]\n```\n\ncan be inferred to have type `(\"RUNNING\" | \"STOPPED\")[]`, and so when it is\npassed into a function with the above type signature, the type parameter `V` is\nthus inferred to be `\"RUNNING\" | \"STOPPED\"`. Then the return type `{ [K in V]: K\n}` is a mapped type which describes an object whose keys are the types that make\nup `V` and for each such key has a value of the same type as that key. Hence,\nthe type of `Enum(\"RUNNING\", \"STOPPED\")` is\n\n``` javascript\n// This is a type, not an object literal.\n{\n    RUNNING: \"RUNNING\";\n    STOPPED: \"STOPPED\";\n}\n```\n\nNext, consider the second overload, which handles the case which takes an object\nof keys and values, and for the sake of example consider\n\n``` javascript\nconst Status = Enum({\n    RUNNING: \"running\",\n    STOPPED: \"stopped\",\n});\n```\nThe second type parameter `V` is inferred as `\"running\" | \"stopped\"`, which\nforces TypeScript to infer the first type parameter `T` as an object whose\nvalues are the specific string values that make up `V`. Hence, even though `{\nRUNNING: \"running\", \"STOPPED\": \"stopped\" }` would have type `{ RUNNING: string;\nSTOPPED: string; }`, passing it through `Enum` causes its type to be inferred\ninstead as the desired\n\n``` javascript\n// Type, not object literal.\n{\n    RUNNING: \"running\";\n    STOPPED: \"stopped\";\n}\n```\n\nNext, consider the definition\n\n``` javascript\ntype Enum\u003cT\u003e = T[keyof T];\n```\n\nThis is an index type which describes, for a given keyed type `T`, the type\nobtained by indexing into `T` with an arbitrary one of its keys (the syntax\n`T[keyof T]` is meant to evoke the expression `t[key]` for some `key` in `t`).\nWhen passing in an arbitrary key to the object from the previous step, we get a\nvalue which might be any one of the object's values, and so its type is thus the\nunion of the types of the object's values. Hence, `Enum\u003ctypeof Enum(\"RUNNING\",\n\"STOPPED\")\u003e` evaluates to `\"RUNNING\" | \"STOPPED\"`, which is what we want.\n\n## Advantages over native string enums\n\nWith the addition of native string enums in TypeScript 2.4, this library will be\nunnecessary for most users. There are still a few niche reasons why users may\nstill prefer to use this library.\n\n* This library provides several helper functions which cannot easy be\n  implemented for native enums. Of these, [`Enum.isType()`](#enumistypeenum-value) will likely be the\n  most useful.\n* Defining a native string enum involves a bit of repetition, as each value must\n  be written twice:\n  ```ts\n  enum Color {\n      RED = \"RED\",\n      GREEN = \"GREEN\",\n      BLUE = \"BLUE\"\n  }\n  ```\n  vs\n  ```ts\n  const Color = Enum(\"RED\", \"GREEN\", \"BLUE\");\n  type Color = Enum\u003ctypeof Color\u003e;\n  ```\n  If there are many values, it may be desirable to avoid the repetition and\n  corresponding possibility for typos.\n\n## Acknowledgements\n\nThis libary is heavily inspired by posts in [this\nthread](https://github.com/Microsoft/TypeScript/issues/3192). In particular,\ncredit goes to users **[@igrayson](https://github.com/igrayson)**,\n**[@nahuel](https://github.com/nahuel)**, and\n**[@kourge](https://github.com/kourge)**.\n\nCopyright © 2017 David Philipson\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdphilipson%2Ftypescript-string-enums","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdphilipson%2Ftypescript-string-enums","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdphilipson%2Ftypescript-string-enums/lists"}