dangcuuson / graphql-schema-typescript

Generate TypeScript from GraphQL's schema type definitions
191 stars 36 forks source link

Use `keyof typeof ` for enums #5

Open qix opened 6 years ago

qix commented 6 years ago

Enum types in TypeScript are not actually just the enum values. The types land up being restricted to string internally rather than the actual values. This makes the types a little stricter.

dangcuuson commented 6 years ago

Hi qix,

Could you explain more about your case?

From my understanding, I think you mean that TypeScript treats enum as equivalent to string.

However, in my projects I have to use the enum values to assign to a variable with corresponding enum type.

E.g:

enum Color {
    RED = 'RED',
    GREEN = 'GREEN',
    BLUE = 'BLUE'
}

const color1: Color = Color.RED; // this one is ok
const color2: Color = 'RED'; // TypeScript complains in this case

however, compare enum value with string is ok

switch (color1) {
    case 'RED': // fine
    case Color.R:  // fine
    case 'YELLOW': { // TypeScript complains in this case
        break;
    }

    default: {
        break;
    }
}

I'm not sure whether if it's due to some different in tsconfig.json file or not.

The reason why I need to clarify this is because there is a catch here: keyof typeof enum refers to the keys of that enum, not the actual value. Therefore, it only works when the enum's keys are the same as its values. E.g:

// note that the enum keys were changed to R/G/B instead of RED/GREEN/BLUE
enum Color {
    R = 'RED',
    G = 'GREEN',
    B = 'BLUE'
}

const color1: Color = Color.R;
console.log(color1); // RED

const color2: keyof typeof Color = 'R'; // assign 'RED' will make TypeScript complains
console.log(color2); // R

This catch is not a problem in this library since the enum keys and values are always the same. However, it could lead to some troubles in the future :) Maybe we could wrap your implementation in a config option?