Home > Net >  Typescript complains when mapping numeric enum to string enum
Typescript complains when mapping numeric enum to string enum

Time:12-09

I'm trying to map a number-based enum generated from a gRPC proto file into a string-based enum for use in my REST API.

The mapping works but TS complain, giving this error.

What have I done wrong, and how to fix?

types/mapping.ts:5:14 - error TS2739: Type '{ 3: OperationMode.LEARNING; 2: OperationMode.MAINTENANCE; 1: OperationMode.NORMAL; 4: OperationMode.TESTING; 0: undefined; }' is missing the following properties from type '{ 0: OperationMode | undefined; OPERATION_UNSPECIFIED: OperationMode | undefined; OPERATION_NORMAL: OperationMode | undefined; ... 6 more ...; 4: OperationMode | undefined; }': OPERATION_UNSPECIFIED, OPERATION_NORMAL, OPERATION_MAINTENANCE, OPERATION_LEARNING, OPERATION_TESTING

5 export const operationModeG2R: {[key in gRPCOperationMode]: OperationMode|undefined} = {
               ~~~~~~~~~~~~~~~~

Code generated by @grpc/proto:

export const OperationMode = {
  OPERATION_UNSPECIFIED: 0,
  OPERATION_NORMAL: 1,
  OPERATION_MAINTENANCE: 2,
  OPERATION_LEARNING: 3,
  OPERATION_TESTING: 4,
} as const;

Code defined in rest-api.ts

export enum OperationMode {
    NORMAL = 'NORMAL',
    MAINTENANCE = 'MAINTENANCE',
    LEARNING = 'LEARNING',
    TESTING = 'TESTING',
  }
import { OperationMode as gRPCOperationMode } from "../proto/generated/companyname/control/OperationMode";
import { OperationMode } from "./rest-api";

export const operationModeG2R: {[key in gRPCOperationMode]: OperationMode|undefined} = {
    [gRPCOperationMode.OPERATION_LEARNING]:OperationMode.LEARNING,
    [gRPCOperationMode.OPERATION_MAINTENANCE]:OperationMode.MAINTENANCE,
    [gRPCOperationMode.OPERATION_NORMAL]:OperationMode.NORMAL,
    [gRPCOperationMode.OPERATION_TESTING]:OperationMode.TESTING,
    [gRPCOperationMode.OPERATION_UNSPECIFIED]:undefined
}

CodePudding user response:

gRPCOperationMode is a runtime value and can not be used inside of a mapped type because mapped types can only work with types.

You want to get the type of gRPCOperationMode using typeof and map over its keys with keyof. But the keys of gRPCOperationMode are string types. Since you want to get the number literal type of each key's value, you need to use key remapping to map each key K into its corresponding type gRPCOperationMode[K].

export const operationModeG2R: { 
  [K in keyof typeof gRPCOperationMode as typeof gRPCOperationMode[K]]: 
    OperationMode | undefined
} = {
    [gRPCOperationMode.OPERATION_LEARNING]:OperationMode.LEARNING,
    [gRPCOperationMode.OPERATION_MAINTENANCE]:OperationMode.MAINTENANCE,
    [gRPCOperationMode.OPERATION_NORMAL]:OperationMode.NORMAL,
    [gRPCOperationMode.OPERATION_TESTING]:OperationMode.TESTING,
    [gRPCOperationMode.OPERATION_UNSPECIFIED]:undefined
}

Playground

CodePudding user response:

The answer from @tobias-s is the correct answer to my particular question.

However, after taking a look in the generated file, I can see that there's already a shorthand type OperationMode__Output for this case, which I want to share to anyone who come here by searching for the specific gRPC related issue:

// Original file: proto/autofuel.proto

export const OperationMode = {
  OPERATION_UNSPECIFIED: 0,
  OPERATION_NORMAL: 1,
  OPERATION_MAINTENANCE: 2,
  OPERATION_LEARNING: 3,
  OPERATION_TESTING: 4,
} as const;

export type OperationMode =
  | 'OPERATION_UNSPECIFIED'
  | 0
  | 'OPERATION_NORMAL'
  | 1
  | 'OPERATION_MAINTENANCE'
  | 2
  | 'OPERATION_LEARNING'
  | 3
  | 'OPERATION_TESTING'
  | 4

export type OperationMode__Output = typeof OperationMode[keyof typeof OperationMode]

Which means I can do it like this:

import { OperationMode as GRPCOperationMode, OperationMode__Output } from "../proto/generated/companyname/control/OperationMode";
import { OperationMode } from "./rest-api";

export const operationModeG2R: { 
  [K in OperationMode__Output]: 
    OperationMode | undefined
} = {
  [GRPCOperationMode.OPERATION_LEARNING]:OperationMode.LEARNING,
  [GRPCOperationMode.OPERATION_MAINTENANCE]:OperationMode.MAINTENANCE,
  [GRPCOperationMode.OPERATION_NORMAL]:OperationMode.NORMAL,
  [GRPCOperationMode.OPERATION_TESTING]:OperationMode.TESTING,
  [GRPCOperationMode.OPERATION_UNSPECIFIED]:undefined
}

  • Related