WORMSS
WORMSS

Reputation: 1664

Static Method on Enum

I have been following declaration-merging for typescript and I copied their example for merging a enum with some functions, and all I did was add export to the enum and now I get errors.

export enum MyEnum {
  Point = 'Point',
  MultiPoint = 'MultiPoint',
}

namespace MyEnum {
  export function parse(val: string): Type {
    return MyEnum[val as keyof typeof MyEnum];
  }
}

[ts] Individual declarations in merged declaration 'MyEnum' must be all exported or all local. [2395]

so fair enough it wants all or nothing, so I export out the namespace too.

export namespace Type { ... }

I now get another error.

[ts] Type 'MyEnum | ((val: string) => MyEnum)' is not assignable to type 'MyEnum'. Type '(val: string) => MyEnum' is not assignable to type 'MyEnum'. [2322]

I am not really sure if I am understanding that error message correctly, but it looks like it is trying to say that the MyEnum type can be either be a value of MyEnum or function is obviously failing, and also not what I was trying to do.

I also tried to remove the export from function parse but then it just becomes unavailable. I have tried adding 'static' in various places but nothing seems to work.

All I am trying to do currently is

const value: string = getString();
const pointType = MyEnum.parse(value);

But I do plan on having more advanced stuff in the future and would just like to understand what I am doing wrong?

Upvotes: 3

Views: 3883

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250036

In adding an extra member to the enum (you are adding parse method) you changed the what indexing into the enum will produce and what the keys of enum will be.

keyof typeof MyEnum is going to be "Point" | "MultiPoint" | "parse", so it will include the extra member.

Also typeof MyEnum[keyof typeof MyEnum] will be MyEnum | ((val: string) => MyEnum), including the new member signature.

You can check for parse (which you may want to handle explicitly) :

export enum MyEnum {
    Point = 'Point',
    MultiPoint = 'MultiPoint',
}

export namespace MyEnum {
    export function parse(val: string): MyEnum {
        const key = val as keyof typeof MyEnum
        if (key === 'parse') throw new Error("parse !");
        return MyEnum[key]
    }
}

Or you can just use an assertion that excludes parse:

export enum MyEnum {
    Point = 'Point',
    MultiPoint = 'MultiPoint',
}

export namespace MyEnum {
    export function parse(val: string): MyEnum {
        return MyEnum[val as Exclude<keyof typeof MyEnum, 'parse'>]
    }
}

Upvotes: 6

Related Questions