Search code examples
reactjsgenericsflowtypestatic-typingflow-typed

How to refactor an enum's type to generic using in flowtype?


Imagine I have 3 enums that have a type of {[key: string]: Type} This is pretty common I thought it would be nice to have an generic to reduce the repeition but I'm nto sure on how to do it: I was thinking something like this:

export interface KeyType<T> {
  [key: string]: T;
}

and use it like so:

KeyType<HeadingOptionType>

But it doesn't work :(.

How can I write a write a type that removes the {[key: string]} repitition in my examples below?

export const HeadingOption: {[key: string]: HeadingOptionType} = {
  H1: 1,
  H2: 2,
  H3: 3,
  H4: 4,
  H5: 5,
  H6: 6,
};

export const EnumColumn: {[key: string]: EnumColumnType} = {
  C1: 1,
  C2: 2,
  C3: 3,
  C4: 4, // not supported yet but should be.
};

export const RtlMirror: {[key: string]: RtlMirrorType} = {
  ON: true,
  OFF: false,
};

Solution

  • I guess you're getting error regarding indexer property. You can get rid of it by changing interface to type alias: type KeyType<T> = { [string]: T };.

    Anyway I don't think such a typing is useful because you'll need manually define a value types. Common practice in flow to describe enums is:

    const HEADING_OPTION = Object.freeze({
      H1: 1,
      H2: 2,
      H3: 3,
      H4: 4,
      H5: 5,
      H6: 6,
    });
    
    type HeadingOption = $Values<typeof HEADING_OPTION>;
    
    let h1: HeadingOption = HEADING_OPTION.H1; // OK
    h1 = 1; // OK
    
    // $Expect error: Cannot assign `999` to `h1` because number is incompatible with enum 
    h1 = 999;