Home > OS >  Typescript: Field's type in a conditional type while passing an enum with a generic
Typescript: Field's type in a conditional type while passing an enum with a generic

Time:11-17

I have a Type<T> which is supposed to have a field additionalField with a type of T[]. I need to make this field optional, depending on if there's a generic being passed. So I introduce a ConditionalType<T = void>, in which if I don't pass a generic - then there's no additionalField.

So I have an enum MyEnum and in ConditionalType<MyEnum> I expect additionalField to be of type MyEnum[]. Instead, additionalField has a type of MyEnum.TEST_1[] | MyEnum.TEST_2[].

Here's the full code:

type ConditionalType<T = void> = {
  someField: string;
} & (T extends void ? {} : {
  additionalField: T[];
})

type Type<T> = {
  someField: string;
  additionalField: T[];
}

enum MyEnum  {
  TEST_1 = "test_1",
  TEST_2 = "test_2"
}

const a: ConditionalType<MyEnum>;
a.additionalField
// (property) additionalField: MyEnum.TEST_1[] | MyEnum.TEST_2[]
// Need to make it MyEnum[] somehow

const b: Type<MyEnum>;
b.additionalField;
// (property) additionalField: MyEnum[]
// Works as expected

Could someone please tell me, how can I make additionalField to be of type MyEnum[] instead of MyEnum.TEST_1[] | MyEnum.TEST_2[] in ConditionalType<MyEnum>? In the original Type<T> it works as expected and additionalField has the type of MyEnum[] in Type<MyEnum>;

And if this is supposed to work this way, why is this happening with ConditionalType<T = void>?

Here's a link to the playground

CodePudding user response:

You accidentally triggered distribution by writing T extends void. The union in T is distributed over the conditional leading to the union MyEnum.TEST_1[] | MyEnum.TEST_2[] instead of (MyEnum.TEST_1[] | MyEnum.TEST_2)[].

Avoid distribution by wrapping T and void inside tuples.

type ConditionalType<T = void> = {
  someField: string;
} & ([T] extends [void] ? {} : {
  additionalField: T[];
})

Playground

  • Related