Skip to content

Enums can not be used for index signature types #13042

Description

TypeScript Version: 2.1.4

export interface UserInterfaceColors {
    [index in UserInterfaceElement]: ColorInfo;
}
export interface ColorInfo {
    r: number;
    g: number;
    b: number;
    a: number;
}
export enum UserInterfaceElement {
    ActiveTitleBar = 0,
    InactiveTitleBar = 1,
}

Expected behavior:
No errors will be thrown.

Actual behavior:
index in UserInterfaceElement throws the error Type 'UserInterfaceElement' is not assignable to type 'string'

This is a regression caused by #12425. The change makes sense, but there are very valid use cases for supporting enums in index signatures.

For another use case, in a project I'm working on, we use an enum to list all types of items. We have a function that takes an object with the enum values as keys, and data as values.

function loadItemData (data: { [index in ItemType]: string }): void;

A workaround is to use index: number, but then it's not enforced that you have to use a valid ItemType as a key.

Original Issue: #2491

Activity

  1. zpdDG4gta8XKpMCd commented on Jan 9, 2017

    @zpdDG4gta8XKpMCd

    can we allow string & Whatever for index signatures too?

  2. RyanCavanaugh commented on Jan 24, 2017

    @RyanCavanaugh
    Member

    Approved.

    Note that this will not cause nominal enforcement of enum index expressions!

    Specifically, [index in UserInterfaceElement]: ColorInfo; will eagerly reduce to "0" | "1" : ColorInfo, so indexing by any other 0- or 1-valued enum value will not cause an error.

  3. amitbeck commented on Mar 22, 2017

    @amitbeck

    Thanks for handling this! Waiting for the fix 👍🏻

  4. 28 remaining items

  5. ChiriVulpes commented on Feb 20, 2018

    @ChiriVulpes
    ContributorAuthor

    Anton Fedchenko (@kompot) That's because you're mapping the enums to string values. You're really just using strings as keys. This issue is for the use of numeric enum entries (which would allow auto-assigned enums to work as well)

    As far as I know, it's worked via string since in and string enums were both present in the language.

  6. kompot commented on Feb 20, 2018

    @kompot

    Well, it definitely didn't work like 6 months ago when I was banging my head trying to get some concise way of exhaustive enum checking. I understand that this is a different issue, yes. But from my understanding getting it work with auto-assigned enums is not that critical when mapped strings enums work this nice.

  7. changed the title [-]Enums can no longer be used for index signature types[/-] [+]Enums can not be used for index signature types[/+] on Feb 20, 2018
  8. bsdunx commented on Mar 11, 2018

    @bsdunx
           const enum UnitType {
                  PLAYER = 0x01,
                  MONSTER = 0x02
           }
           const descriptor = ({
                [UnitType.PLAYER as number]: Player.descriptor,
                [UnitType.MONSTER as number]: Monster.descriptor
            })[type]
    

    Doing it like so may help some in the interim

  9. mhegazy commented on Apr 26, 2018

    @mhegazy
    Contributor

    Should be fixed by #23592

  10. gyandeeps commented on May 31, 2018

    @gyandeeps

    Was this actually fixed by #23592 ?
    Using TS 2.9.1,

    enum Test {
        A = "a",
        B = "b"
    }
    export interface PhaseApi1 {
        [x in Test]: () => void;
    }

    still have issues

    * A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
    * A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
    * Cannot find name 'x'.

    Playground link

  11. mhegazy commented on May 31, 2018

    @mhegazy
    Contributor
    enum Test {
        A = "a",
        B = "b"
    }
    type PhaseApi1 = {
        [x in Test]: () => void;
    };
  12. timkinnane commented on Jul 11, 2018

    @timkinnane

    Just a postmortem FYI for anyone who's gone through what I did, trying for hours to solve this with all manner of type rejigging to remove index signature errors... Make sure your IDE linter has the latest version of Typescript. Those errors might not actually be errors at all.

    +1 for the 😭 reaction option.

  13. aboyton commented on Aug 7, 2018

    @aboyton

    Mohamed Hegazy (@mhegazy) Any reason that this works for type and not interface? I know it's easy to use one over the other but it seems a strange restriction.

  14. VitamintK commented on Feb 1, 2019

    @VitamintK

    It's unlikely that this happens to anyone else but me, but if you're trying to figure out why the fix isn't working for you, check that you spelled your enum correctly.

  15. kg-currenxie commented on Apr 17, 2020

    @kg-currenxie
    enum Test {
        A = "a",
        B = "b"
    }
    type PhaseApi1 = {
        [x in Test]: () => void;
    };

    Is there a way to make either key optional?

  16. ChiriVulpes commented on Apr 17, 2020

    @ChiriVulpes
    ContributorAuthor

    Kristian Gerardsson (@kg-currenxie)

    type PhaseApi1 = {
        [x in Test]?: () => void;
    };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

CommittedThe team has roadmapped this issueFixedA PR has been merged for this issueSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions