[TypeScript] Using Enums

Hello all,

I have managed to confuse myself again… I think it is fairly intuitive what I am trying to achieve, but TS disagrees:

const obj: BaseType = {
  filters: [
        {
          filterType: "PRICE_FILTER",
          minPrice: "0.00000100",
          maxPrice: "100000.00000000",
          tickSize: "0.00000100",
        },
        {
          filterType: "PERCENT_PRICE",
          multiplierUp: "1.3000",
          multiplierDown: "0.7000",
          avgPriceMins: 5,
        },
}
interface BaseType {
  filter: SymbolFilterTypes[];
}

type SymbolFilterTypes =
  | PriceFilter
  | PercentPrice;

enum FilterTypes {
  PRICE_FILTER = "PRICE_FILTER",
  PERCENT_PRICE = "PERCENT_PRICE"
}

type PriceFilter = {
  filterType: FilterTypes.PRICE_FILTER;
  minPrice: string;
  maxPrice: string;
  tickSize: string;
};

type PercentPrice = {
  filterType: FilterTypes.PERCENT_PRICE;
  multiplierUp: string;
  multiplierDown: string;
  avgPriceMins: number;
};

However, I get this complaint:

Type '"PRICE_FILTER"' is not assignable to type 'FilterTypes'.deno-ts(2322)

Any help understanding the best semantic way to do this would be appreciated.

In TS an Enum is a type and a value. You need to use the Enum in your object/data the same as you have in your type definitions.

Thank you, but this data does not come from me - I have used it as an example response. So, I cannot use the enum in the variable.

Ok. Where is the error is showing up? What is the purpose of the example response data? I don’t understand why you aren’t able to edit it.

The error is showing up as shown in the image.

I have created example responses so I can run some unit tests ensuring the types behave themselves. As such, the example data comes from an external API (I have no control over its typing).

I realise I could just use static strings as the types, but thought enums made sense, and kind of wanted to get to know them :man_shrugging: . Should I just go with?:

type PriceFilter = {
  filterType: "PRICE_FILTER";
  ...
}

I feel like it should be

const obj: BaseType = {
  filters: [
        {
          filterType: FilterTypes.PRICE_FILTER,
          minPrice: "0.00000100",
          maxPrice: "100000.00000000",
          tickSize: "0.00000100",
        },
        {
          filterType: FilterTypes.PERCENT_PRICE,
          multiplierUp: "1.3000",
          multiplierDown: "0.7000",
          avgPriceMins: 5,
        },
  ]
}

Not

const obj: BaseType = {
  filters: [
        {
          filterType: "PRICE_FILTER",
          minPrice: "0.00000100",
          maxPrice: "100000.00000000",
          tickSize: "0.00000100",
        },
        {
          filterType: "PERCENT_PRICE",
          multiplierUp: "1.3000",
          multiplierDown: "0.7000",
          avgPriceMins: 5,
        },
}

But both compile for me, see typescript playground link

I’m not quite sure what you’re doing here, I can’t see how you’re gaining anything by using enums (which are not particularly ergonomic at the best of times); I would just use literals in a union type instead if you want to enforce the typings on the filters

I would probably, if you’re going to keep going with enums, use them as keys in an object in, rather than an array, like

obj = {
  filters: {
    [FilterTypes.PRICE_FILTER]: {
      ...etc
    },
    [FilterTypes.PERCENT_PRICE]: {

but even then, can use literals, for example

type FilterType = "PRICE_FILTER" | "PERCENT_PRICE";

interface BaseType = {
  filters: {
    [T of FilterType]: Filter
  }
}

Thank you, for the help.

As mentioned, I do not have control over the data response. So, cannot do this on the filters property:

Hmm… Odd, but I have just been using the default Deno TS config :man_shrugging:

The learning aspect, mostly. :laughing: . I suppose I am just wanting to figure them out, because they exist, and, at least initially, looked useful.

I suppose, for the sake of continuing forward with the project, it has come to this :disappointed:

1 Like

I have created example responses so I can run some unit tests ensuring the types behave themselves. As such, the example data comes from an external API (I have no control over its typing).

The types from the API won’t conflict with your Enum at run time. The value of the Enum member is a string in this case.

Can you add another screenshot of the error in your editor? I don’t understand where you are encountering the error besides the mock response data.

1 Like

I wouldn’t be sad about it :grinning_face_with_smiling_eyes: – enums are a pain because they straddle types and values, they do have uses but they’re not great and if you can avoid them (which you can do here via string literal types), it’s probably for the best

1 Like

This is nice to know, but does that mean I should just not type the test object? That is, remove : BaseType?

I could, but it would look almost identical :sweat_smile: . If you can see the squiggly red lines under the filterType property - I hover over that, and the tooltip with the type error appears.

You should be able to use filterType: FilterTypes.PRICE_FILTER; in the mock data to resolve the type errors. The value of the Enum member is the same as the string value of the API response so there shouldn’t be any runtime errors as a result.

You can type with a string union as well. But if you want to use Enums that is how to do it.

1 Like