1

I have an autogenerated enum (from NSwag) which generates me the following:

export enum Frequency {
  Weekly = 1, 
  Fortnightly = 2, 
}

For my interface I want to say that it's a string value that must have come from the Frequency. The closest I got was:

interface GtmProduct {
  dimension6: keyof Frequency;
}

I also tried dimension6: 'weekly' | 'fortnightly' to no avail.

In usage it looks like this:

{ ...
  dimension6: Frequency[frequency].toLowerCase() //frequency here will be `Frequency.Weekly`
}

This errors with: Type 'string' is not assignable to type '"toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"'.

Is there any way to achieve what I want using TS 2.9 or should I simply type it as a string?

Kyle Muir
  • 3,875
  • 2
  • 22
  • 27
  • "For my interface I want to say that it's a string value that must have come from the Frequency" What do you mean by this? – aframestor Aug 27 '18 at 08:17
  • you may need to process the enum in a similar fashion in this question: https://stackoverflow.com/questions/18111657/how-does-one-get-the-names-of-typescript-enum-entries – tonakai Aug 27 '18 at 08:21
  • @aframestor what I meant by this was I want the only acceptable values for `dimension6` to be either `Weekly` or `Fortnightly`. If `Frequency` was to get another value (i.e. `Monthly`) then I would want that to "just work" without further code changes to this area. – Kyle Muir Aug 27 '18 at 10:40
  • I see what you mean now. However I don't think you can achieve what you want without using a custom type for dimension6. If you want it to be a string you'll have to implement these constraints logically. – aframestor Aug 27 '18 at 10:47

2 Answers2

1

First of all - you have to use keyof typeof Frequency in order to get union type of '"Weekly" | "Fortnightly"'. Follow this TS issue 14294 for more details.

enter image description here Also you can use type casting when you set GtmProduct values. So here is the final solution:

type KeyOfFrequencey = keyof typeof Frequency;

interface GtmProduct {
  dimension6: KeyOfFrequencey;
}

const toKeyOf = (f: Frequency): KeyOfFrequencey => Frequency[f] as KeyOfFrequencey;

const frequency = Frequency.Weekly
const a: GtmProduct = {
  dimension6: toKeyOf(frequency)
}

But in your example I see .toLowerCase() which is probably not correct, since your Enum keys have uppercased properties and you're going to lowercase them in your interface. This is why I removed lowercase in my example.

If you want to use lowercased values, than you have to use lowercased keys in your enum as well:

enum Frequency {
  weekly = 1, 
  fortnightly = 2, 
}

Try this example in this stackblitz

shohrukh
  • 2,989
  • 3
  • 23
  • 38
  • Unfortunately I have no control over how the `Frequency` enum is generated (it's autogenerated by a tool as a much smaller part of the overall system) so changing how those are generated is unfortunately out of the question. Thanks for the above though, that is a really good starting point. – Kyle Muir Aug 27 '18 at 10:39
  • U r welcome. But why you need `toLowerCase()` the Enum props ? – shohrukh Aug 27 '18 at 10:41
  • Our existing enhanced ecomm tracking has been set up with lower case frequency so I was hoping to get parity in our new area. Whether or not GTM cares about case is a separate question I'll need to check I guess. – Kyle Muir Aug 27 '18 at 10:42
  • Got it. So this case you can lower case the properties inside `toKeyOf` method: `Frequency[f].toLocaleLowerCase() as KeyOfFrequencey`. I don't see any problems here. – shohrukh Aug 27 '18 at 10:51
  • 2
    Heh, you were one step ahead of me. Just got it working with that as well. Thanks again! – Kyle Muir Aug 27 '18 at 10:53
-1

You want to get i.e. 'weekly' in the dimension6 variable? Have a look to https://www.typescriptlang.org/docs/handbook/enums.html it is a Reverse Mapping you want.

Lord_Pinhead
  • 127
  • 1
  • 10