Search code examples
typescriptcomputed-properties

How can a string constant be used as a computed identifier in a union type in TypeScript?


I have the following union type:

interface Cell {};

type CellInfo =
  | { Provisioned: Cell }
  | { Cloned: Cell };

Is there a way to use a computed property identifier instead of a string literal? E. g.

interface Cell {};

const PROVISIONED = "Provisioned";

type CellInfo =
  | { [PROVISIONED]: Cell }
  | { Cloned: Cell };

This works. Now I'd like to use an object or an enum instead of individual constants. Enums cannot be used for computed properties, but this doesn't work either:

interface Cell {};

const CELL_TYPE = {
    PROVISIONED: "Provisioned",
    CLONED: "CLONED",
};

type CellInfo =
  | { [CELL_TYPE.PROVISIONED]: Cell }
  | { [CELL_TYPE.CLONED]: Cell };

The computed property's error message is A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.(1170).

Why is that and how can I do it?


Solution

  • There are 2 ways to do it, one already mentioned by @CRice, another one is do const assertion on individual properties, this is a more granular approach

    interface Cell {};
    
    const CELL_TYPE = {
        PROVISIONED: "Provisioned" as const,
        CLONED: "CLONED" as const,
    };
    
    type CellInfo =
      | { [CELL_TYPE.PROVISIONED]: Cell }
      | { [CELL_TYPE.CLONED]: Cell };
    

    playground