Home > front end >  How to tell typescript I'm passing object with a key of specific enum keys?
How to tell typescript I'm passing object with a key of specific enum keys?

Time:03-07

The following throws an error: Types of property 'type' are incompatible. Type 'MyEnum' is not assignable to type 'MyEnum.C | MyEnum.D'.

I understand what it means, but cannot find a good solution to it.

enum MyEnum {
   B,
   C,
   D,
}

interface MyInterface {
   type: MyEnum
   otherData: string
}

function func1(data: MyInterface): void {
   if (
       data.type === MyEnum.C ||
       data.type === MyEnum.D
   ) {
      func2(data) // throws an error
   }
}

function func2(
    data: Omit<MyInterface, 'type'> & {
       type:
          | MyEnum.C
          | MyEnum.D
    },
): void {}

How to tell typescript I'm going to work with data whose key type is either MyEnum.C or MyEnum.D?

CodePudding user response:

You could cast data to the required type:

enum MyEnum {
    A, B, C, D
}

interface MyInterface {
    type: MyEnum;
}

type MyInterfaceCD = Omit<MyInterface, 'type'> & {
       type:
          | MyEnum.C
          | MyEnum.D
    };

function func1(data: MyInterface): void {
   if (
       data.type === MyEnum.C ||
       data.type === MyEnum.D
   ) {
      func2(data as MyInterfaceCD) // throws an error
   }
}

function func2(
    data: Omit<MyInterface, 'type'> & {
       type:
          | MyEnum.C
          | MyEnum.D
    },
): void {}

CodePudding user response:

You can change move the condition to a function with return type which check for a type. like this:

enum MyEnum {
    A,B,C,D

}

interface MyInterface {
    type: MyEnum;
}

interface OmittedInterface extends Omit<MyInterface, 'type'>  {
       type: MyEnum.C | MyEnum.D
}

function isOmittedInterface(data: MyInterface): data is OmittedInterface {
    return data.type === MyEnum.C || data.type === MyEnum.D
}

function func1(data: MyInterface): void {
   if (isOmittedInterface(data)) {
      func2(data);
   }
}

function func2(
    data: Omit<MyInterface, 'type'> & {
       type:
           MyEnum.C
          | MyEnum.D
    },
): void {}

The return type of isOmittedInterface will make typescript look at the type as OmittedInterface if its return true

  • Related