Skip to content

Enable constants as computed values for string enums #40793

Closed

Description

@kataik

Search Terms

'TS18033', 'typescript define enum with constant string value', 'string enum computed constant'

Suggestion

Please consider enabling to use constant variables as values for string enums. The following code snippet fails compilation with TS18033 ('Only numeric enums can have computed members, but this expression has type 'string'. If you do not need exhaustiveness checks, consider using an object literal instead.')

const VALUE: string = 'ENUM_VALUE';

enum MyEnum {
  KEY = VALUE, // <-- Fails with TS18033
}

console.log(MyEnum.KEY);

, whereas the following passes:

enum Values {
  VALUE = 'ENUM_VALUE',
}

enum MyEnum {
  KEY = Values.VALUE,
}

console.info(MyEnum.KEY);

Use Cases

Use string interpolation (templated strings) when defining the value of a string enum to be able to reuse pre-defined constants as part of the value. (E.g. namespace prefixes, extension postfixes)

Examples

const NAMESPACE: string = 'com.mycompany.myservice';

enum Errors {
  INVALID_INPUT_ERROR = `${NAMESPACE}.errors#InvalidInput`,
}

Checklist

My suggestion meets these guidelines:

  • [ X ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [ X ] This wouldn't change the runtime behavior of existing JavaScript code
  • [ X ] This could be implemented without emitting different JS based on the types of the expressions
  • [ X ] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [ X ] This feature would agree with the rest of TypeScript's Design Goals.

Activity

  1. Inlesco commented on Oct 11, 2020

    @Inlesco

    This would be a perfectly valid feature to implement since computed number values are already allowed.

    Is there any reason why computed string values shouldn't be allowed for enums? Perhaps I'm not aware of something tied to the bigger picture?

    Ryan Cavanaugh (@RyanCavanaugh) can anybody from the TS team comment on my assumptions above? Thanks a lot.

  2. moneydance commented on Nov 12, 2020

    @moneydance

    I'm also curious about why computed enums are disabled for strings. Being able to use templated strings would be great. Looks like there was a similar issue here #20440.

  3. fenduru commented on Apr 16, 2021

    @fenduru

    This would be handy when when writing a React component with a prop that controls a css class. Right now I'm doing the following

    enum ComponentVariant {
      Foo,
      Bar,
    }
    
    const classes = {
      [ComponentVariant.Foo]: styles.fooClassName,
      [ComponentVariant.Bar]: styles.barClassName,
    }
    
    export default function TheComponent({ variant }: {variant: ComponentVariant}) {
      return <div className={classes[variant]} />
    }

    But it would be both cleaner, and also safer (i.e. prevent accidentally indexing into a non-existing value in the classes object) to do this directly:

    enum ComponentVariant {
      Foo = styles.fooClassName,
      Bar = styles.barClassName,
    }
    
    export default function TheComponent({ variant }: {variant: ComponentVariant}) {
      return <div className={variant} />
    }
  4. tomasdev commented on May 1, 2021

    @tomasdev

    Following the namespace reasoning, highly useful for developing browser extensions or other scripts where we don't want to collision with pre-existing scripts, such as postMessage(<this value>, '*')

  5. ahnpnl commented on Jul 6, 2021

    @ahnpnl

    I also need this

  6. RebeccaStevens commented on Nov 19, 2021

    @RebeccaStevens

    Additionally symbols should be allowed to be used as enum values.

    enum MyType {
        foo = Symbol("foo"), // Error: ts(18033) - Only numeric enums can have computed members, but this expression has type 'symbol'. If you do not need exhaustiveness checks, consider using an object literal instead.
    }
  7. Thorugoh commented on Nov 19, 2021

    @Thorugoh

    I'm with the same problem :/

  8. nxpatterns commented on Nov 29, 2021

    @nxpatterns

    please enable, thank you!

  9. daltonrussell commented on Dec 20, 2021

    @daltonrussell

    Facing the same issue. I would love to have computed values for strings so I can assign react components to enums.

  10. SheppardX commented on Jan 10, 2022

    @SheppardX

    PUSH!! i am currently facing this issue too.
    have an ENUM with endpoints and want to reuse pre-defined parts of that

    export const customerEndpoint = '/customers';
    
    export enum ENDPOINTS {
      INVOICES = `${customers}/invoices`,
      BASKET = `${customers}/basket`,
    }
    

    as an example

  11. zheoreh commented on Jan 19, 2022

    @zheoreh

    +1

  12. estefafdez commented on Feb 14, 2022

    @estefafdez

    I would love to have this on TS, thanks!

  13. JordanDC2 commented on Mar 9, 2022

    @JordanDC2

    This would be a great feature, currently running into this same issue

  14. 37 remaining items

  15. vfa-locltb commented on Dec 1, 2022

    @vfa-locltb

    +1

  16. RyanCavanaugh commented on Dec 13, 2022

    @RyanCavanaugh
    Member

    Why are people +1ing an implemented feature?

  17. handletastic commented on Dec 13, 2022

    @handletastic

    Why are people +1ing an implemented feature?

    Probably because people don't yet know of it? 🤷🏻‍♂️ I mean it's been implemented like a month ago only.

  18. youthug commented on Mar 14, 2023

    @youthug

    Hey guys, how to fix this error?

    got this in playground (TS version: the latest Nightly):

    const enum member initializers must be constant expressions.(2474)

    image

    and this in IntelliJ IDEA (TS version: 5.0.1-rc)

    TS18033: Type 'string' is not assignable to type 'number' as required for computed enum member values.

  19. dfl-zeke commented on Mar 16, 2023

    @dfl-zeke

    Why are people +1ing an implemented feature?

    It's been a 4-5 months and still not included into latest release, wym.

  20. RyanCavanaugh commented on Mar 17, 2023

    @RyanCavanaugh
    Member

    5.0 came out yesterday and includes this feature.

  21. afarah1 commented on Jun 2, 2023

    @afarah1

    I have a use case like this which still yields TS18033 on 5.0.4:

    const fooStr = 'foo';
    
    export const myStrings = {
        foo: fooStr,
    };
    
    enum MyEnum {
      FOO = myStrings.foo,
    };
    
  22. dburgos92 commented on Jul 6, 2023

    @dburgos92

    On 5.0.4 with angular this doesn't work:

    export enum Section{ ASIGN = GlobalConstants.ASIGN DISTRIBUTION = "Distribucion" }

  23. nick4fake commented on Jul 26, 2023

    @nick4fake

    Ryan Cavanaugh (@RyanCavanaugh) this is still an issue even with TS 5.1.6:

    image

  24. hanzheliva commented on Aug 3, 2023

    @hanzheliva
    Screenshot 2023-08-02 at 9 16 12 PM

    Ryan Cavanaugh (@RyanCavanaugh) Could you please check what the cause of this problem is?

  25. RyanCavanaugh commented on Aug 3, 2023

    @RyanCavanaugh
    Member

    The error message means what it says.

  26. AlexKDawson commented on Aug 7, 2023

    @AlexKDawson

    Ryan Cavanaugh (@RyanCavanaugh) I think people (myself included) are still seeing this warning after installing TS >5.0
    I'd expect this error to not appear if the feature was implemented?

    I felt I should clarify... but I have the same question as Hanzhe Li (@hanzheliva) above.

    Since const haha = null || "haha" is a constant expression evaluating in typescript as "haha" (not as a string) shouldn't the above code be valid? Or at least be more clear?

    I personally think using hard-coded constant expressions (with operators in them) is a bit of a code stink. But I am curious as to how typescript evaluates what is a const expression and what isn't. Are we explicitly not allowed use conditional operators in the declaration of enums even when the expression iteself can be evaluated statically?

  27. AlexKDawson commented on Aug 8, 2023

    @AlexKDawson

    Side Note: I've seen a couple examples of people trying to do the same with ternary expressions, but the key difference being that typescript still evaluates the following

    const foo = true ? 'x' : 'y';

    as foo: 'x'|'y' despite that it could technically be evaluated as a const expression foo: 'x'

    So for anyone curious, ternary expressions still won't work but at least it makes sense why.

  28. mgol commented on Oct 4, 2023

    @mgol

    Issues with using one string enum in another seem like TS bugs; I reported a separate issue for this:
    #55978
    Please upvote if you hit this, too.

    Flagged code, for reference:

    enum E1 {
      A = 'A',
    }
    
    const enums = {
      E1,
    };
    
    enum E2 {
      A = enums.E1.A,
    }
  29. grigorii-lutkov commented on Jan 28, 2025

    @grigorii-lutkov

    Hmm.... this should work, right?

    const option2 = 'option2';
    const option3 = 'option3' as const;
    
    export enum TestEnum {
      Option1 = 'option1',
      Option2 = option2, // <<< no errors here
      Option3 = option3, // <<< ts(18033) error here
    }
    Image

    TS version: 5.6.2


    I've created an issue #61064

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

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureFix AvailableA PR has been opened for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions