5

I was wanting to use conditional types for a rest parameter but I was surprised when I did a test first

Here is a playground and here is the code:

type ExtractParts<P extends any[]> =
    P extends [infer H, ...infer U]
      ? ['yes way']
      : ['no way']


interface A {
  description: string;
  action: () => {
      say: string;
      it: string;
  };
}

type Q = ExtractParts<[1,2,3]> // ['yes]
type P = ExtractParts<A[]>; // ['no way']

type R = ExtractParts<[{    // ['yes way']
  description: string;
  action: () => {
      say: string;
      it: string;
  };
}]>;

I was surprised by this behaviour

type P = ExtractParts<A[]>; // ['no way']

But this works as I think because it is a strict tuple

type R = ExtractParts<[{    // ['yes way']
  description: string;
  action: () => {
      say: string;
      it: string;
  };
}]>;

I wanted to use this technique with a rest parameter

type ExtractParts<P extends any[]> =
    P extends [infer H, ...infer U]
      ? ['yes way']
      : ['no way']


function parts<P extends any[]>(...parts: ExtractParts<P>){}

const b = parts(1,2,3);

But P extends [infer H, ...infer U] returns false

Can I use conditional types like this to infer the head and tail for rest parameters?

1 Answer 1

2

The problem arises from the fact that an array can have 0 elements, while the tuple [H, ...T] must have at least one element. You can define a tuple with an optional first element, [H?, ...T] and that will be a base type for an array.

So in a conditional type you would use [(infer H)?, ...infer U]

type ExtractParts<P extends any[]> =
    P extends [(infer H)?, ...infer U]
      ? ['yes way']
      : ['no way']


interface A {
  description: string;
  action: () => {
      say: string;
      it: string;
  };
}


type Q = ExtractParts<[1,2,3]> // ['yes way']
type P = ExtractParts<A[]>; // ['yes way']

Playground Link

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.