Home > Net >  TypeScript spread operator transform boolean to true | false when type compute
TypeScript spread operator transform boolean to true | false when type compute

Time:03-26

I'm taking type-challenge exercise with the easy part, implement the type version of Unshift.(https://github.com/type-challenges/type-challenges/tree/master/questions/3060-easy-unshift) Here is my code:

type Unshift<T extends unknown[], U> = U extends unknown[]
  ? [...U, ...T]
  : [U, ...T]

the problem is with boolean type:

type Res = Unshift<['1', 2, '3'], boolean>
// expected: [boolean,'1',2,'3']
// actual: [false,'1',2,'3'] | [true,'1',2,'3']

I don't know why is that and how to get expected result. BTW, I got a pretty similar solution from another answer(Typescript spread operator for type),

type Cons<H, T extends readonly any[]> =
    ((h: H, ...t: T) => void) extends ((...r: infer R) => void) ? R : never

is it a trick that should be rote?

CodePudding user response:

The reason you get a union result type is that boolean is a union (true | false) and conditional types distribute over union types (docs). Because of this, Unshift<['1', 2, '3'], boolean> evaluates to Unshift<['1', 2, '3'], true> | Unshift<['1', 2, '3'], false>.

You can prevent it from happening by surrounding both sides of the extends condition with square brackets:

type Unshift<T extends unknown[], U> = [U] extends [unknown[]]
  ? [...U, ...T]
  : [U, ...T]

type Res = Unshift<['1', 2, '3'], boolean>
// type Res = [boolean, "1", 2, "3"]

TypeScript playground

  • Related