Skip to content

Enumerate String Literal Union Values at Runtime #13542

Closed

Description

@battmanz

TypeScript Version:
2.1.4

Code

// Would like to do this:
type Greeting = 'hi' | 'hola' | 'hallo' | 'salut';
const allGreetings: Greeting[] = keyof Greeting; // Error!

// Currently, I am forced to do this:
type Greeting = 'hi' | 'hola' | 'hallo' | 'salut';
const allGreetings: Greeting[] = ['hi', 'hola', 'hallo', 'salut'];

Expected behavior:
I have a need to get all values from a String Literal Union Type at runtime as an array. It would be great if the keyof operator (or some other operator) provided this functionality.

Actual behavior:
Currently, there is no way to do this besides just manually copying all of the values into an array.

Activity

  1. RyanCavanaugh commented on Jan 17, 2017

    @RyanCavanaugh
    Member

    Is #3192 what you actually want?

  2. battmanz commented on Jan 17, 2017

    @battmanz
    Author

    I believe that would suit my needs. However, assuming that the language had both string enums and string literal unions, I think I would be torn between which to use. Would the rule be to use a string enum when you want to enumerate the values and otherwise use a string literal union?

    They both seem to accomplish the same thing in different ways.

  3. RyanCavanaugh commented on Jan 17, 2017

    @RyanCavanaugh
    Member

    I think the difference would simply be whether or not you wanted the strings to be available at runtime. The type system is always fully erased so there's not going to be a way to emit different code depending on what a type system object is (see https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals)

  4. battmanz commented on Jan 25, 2017

    @battmanz
    Author

    Just out of curiosity, how is it that enums don't break the "fully-erasable type system" rule? I mean, enums don't exist in JavaScript. So I would consider them to be part of the type system, but they are not erased at runtime. They are compiled into a two-way associative array. So how would it be any different to emit an array of string literal values at runtime? I just want to increase my understanding. Thanks!

  5. RyanCavanaugh commented on Jan 25, 2017

    @RyanCavanaugh
    Member

    The type system is erased (consider how generics are erased in Java even though generic classes still create code) but declarations which are specified to create values still create values.

    The distinction here is that you can syntactically analyze (not typecheck) a file and produce the correct JavaScript; this would not be true for an unerased type system. Basically, the type of any given expression (as determined by the checker) does not change how it behaves at runtime.

  6. battmanz commented on Jan 25, 2017

    @battmanz
    Author

    Ryan Cavanaugh (@RyanCavanaugh) thanks for the quick reply and such a good reply at that! It's going to take some time for me to digest everything that you said.

    But in the meantime, it sounds like string-based enums are the way to go. So I'm going to close this bug.

  7. pelotom commented on Feb 27, 2017

    @pelotom

    Hi, check out my library runtypes for a solution to this problem. Example usage:

    // Define the runtype
    const Day = Union(
      Literal('Sunday'),
      Literal('Monday'),
      Literal('Tuesday'),
      Literal('Wednesday'),
      Literal('Thursday'),
      Literal('Friday'),
      Literal('Saturday'),
    )
    
    // Extract the static type
    type Day = Static<typeof Day> // = 'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday'
    
    // Extract enumerated literal values
    const days: Day[] = Day.alternatives.map(lit => lit.value)
    
    for (const day of days) {
      console.log(`Good morning, it's ${day}!`)
    }
  8. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions