Skip to content

enum with bigger integer than available is allowed #8020

Closed

Description

Code

export enum ModelType {
  Repositories,
  Gists
};

function test(modelType: ModelType) {

}

test(2);

Example
Expected behavior:

Throw error, because 2 shouldn't be available in ModelType.

Actual behavior:

No error is thrown.

Activity

  1. RyanCavanaugh commented on Apr 12, 2016

    @RyanCavanaugh
    Member

    We don't distinguish between flag and non-flag enums, so a number that is above any given enum member isn't necessarily invalid. For example

    enum Flags {
      Neat = 1,
      Cool = 2,
      Great = 4
    }
    // like saying Neat | Cool | Great
    var x: Flags = 7;
  2. donaldpipowitch commented on Apr 12, 2016

    @donaldpipowitch
    ContributorAuthor

    Can I opt-out from that? This is unexpected for me and for my use cases not useful. Or can I use strings as values and reference them like ModelType.Gists (instead of using 'foo' | 'bar' and use strings directly).

  3. RyanCavanaugh commented on Apr 12, 2016

    @RyanCavanaugh
    Member

    There's no opt-out setting. Can you show an example of what you mean about using strings?

  4. donaldpipowitch commented on Apr 12, 2016

    @donaldpipowitch
    ContributorAuthor

    Say the function test only accepts 'foo' or 'bar' as possible types. I could do it that way:

    type Value = 'foo' | 'bar';
    
    function test(value: Value) {
    
    }
    
    test('foo');
    

    However I need to pass 'foo'``directly which can be troublesome for refactoring. I'd rather pass something likeValue.fooas a reference to'foo'` (which also reads nicer in my opinion). Is this possible somehow? The best thing I can come up with is this beast:

    type Value = 'foo' | 'bar';
    
    type IValueMap = {
      foo: 'foo',
      bar: 'bar'
    };
    
    const ValueMap: IValueMap = {
      foo: 'foo',
      bar: 'bar'
    };
    
    function test(value: Value) {
    
    }
    
    test(ValueMap.foo);
    

    (You need IValueMap or you'll get Argument of type 'string' is not assignable to to parameter of type '"foo" | "bar"'.)

    Going back to my original example I probably would like something like enum, but as a fixed dictionary (which would compile to the same output as my last example with IValueMap):

    export dictionary ModelType {
      Repositories: 'repos',
      Gists: 'gists
    };
    
    function test(modelType: ModelType) {
    
    }
    
    test(ModelType.Repositories);
    test('repos'); // this would work, too
    

    Conclusion

    Maybe I should rather write a dictionary proposal which works exactly like this?:

    export dictionary ModelType {
      Repositories: 'repos',
      Gists: 'gists'
    };
    
    function test(modelType: ModelType.Value) {
    
    }
    

    compiles to

    type ModelTypeValue = 'repos' | 'gists';
    
    type IModelType = {
      Repositories: 'repos',
      Gists: 'gists'
    };
    
    const ModelType: IModelType = {
      Repositories: 'repos',
      Gists: 'gists'
    };
    
    export ModelType;
    
    function test(modelType: ModelTypeValue) {
    
    }
    
  5. Elephant-Vessel commented on Apr 12, 2016

    @Elephant-Vessel

    I also think that the flag-behavior of enums would have been nice to have separated into another keyword like flag since that behavior is really different from the common usage of enums as a a simple set of named constant values.

    However I'm unsure and curious about what you want to achieve here, why don't you just reference the enum value on the ModelType directly like test(ModelType.Gists) instead of sending in wild integers if you want more safety and improving refactoring?

  6. donaldpipowitch commented on Apr 12, 2016

    @donaldpipowitch
    ContributorAuthor

    However I'm unsure and curious about what you want to achieve here, why don't you just reference the enum value on the ModelType directly like test(ModelType.Gists) instead of sending in wild integers if you want more safety and improving refactoring?

    Oh, I don't want the send integers directly. I do use the reference like ModelType.Gists. I found that by accident and thought it was a bug.

  7. Elephant-Vessel commented on Apr 13, 2016

    @Elephant-Vessel

    Donald Pipowitch (@donaldpipowitch) So that stuff about strings, how would that improve the language?

  8. donaldpipowitch commented on Apr 13, 2016

    @donaldpipowitch
    ContributorAuthor

    You could reference the string instead of passing it directly. Or what do you mean?

  9. Elephant-Vessel commented on Apr 13, 2016

    @Elephant-Vessel

    I mean, this is still about how to work with enums right? Or have this issue changed to be about the general possibility to reference values in string literal types like we do with enums?

  10. donaldpipowitch commented on Apr 13, 2016

    @donaldpipowitch
    ContributorAuthor

    I mean, this is still about how to work with enums right?

    Yeah. I'd definitely like to see an enum alternative to not allow things like that:

    export enum ModelType {
      Repositories,
      Gists
    };
    
    function test(modelType: ModelType) {
    
    }
    
    test(2);
    

    Or have this issue changed to be about the general possibility to reference values in string literal types like we do with enums?

    That would probably a second issue. However this could both be solved with the same feature, if I could define an enum with limited custom values (which could be just 0 and 1 or 'gists' and 'repos').

  11. mhegazy commented on Apr 13, 2016

    @mhegazy
    Contributor

    The issue referenced in OP is by design as noted in #8020 (comment)

    The rest of the discussion is about non-number based enums, and this is already tracked by #1206.

  12. andremarcondesteixeira commented on Jul 16, 2017

    @andremarcondesteixeira

    maybe, you guys could use:

    export class MyClass {
        public teste(bla : foo) : void {
            console.log(bla);
        }
    
        public teste2() : void {
            this.teste(weekDay.Sábado);
        }
    }
    
    enum weekDay {
        Domingo,
        Segunda,
        Terça,
        Quarta,
        Quinta,
        Sexta,
        Sábado
    }
    
    export type foo = weekDay.Sábado | weekDay.Domingo;
    

    It will throw the desired errors, and will preserve refactoring capabilities.

  13. 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