0

I have a type:

type Action<I extends unknown[], O> = (...args: I) => Promise<O>;

and some test cases:

// should be [boolean, string]
type TestInput = Input<Action<[boolean, string], number>>;
// should be number
type TestOutput = Output<Action<[boolean, string], number>>;

I wrote the Input type using unknown for O and it works:

type Input<A> = A extends Action<infer I, unknown> ? I : never;

then I wrote the Output type using unknown[] for I:

type Output<A> = A extends Action<unknown[], infer O> ? O : never;

and it doesn't works, the TestOutput is never.

But when I changed unknown[] to any[] it works:

type Output<A> = A extends Action<any[], infer O> ? O : never;

Can anyone explain why?

P.S. I also wrote this test:

type Test = [boolean, string] extends unknown[] ? true : false;

and the Test is true, so I don't understand why the Output with unknown[] for I is not works.

Just Alex
  • 183
  • 1
  • 12
  • 1
    https://stackoverflow.com/questions/51439843/unknown-vs-any – Dave Meehan May 14 '22 at 08:34
  • 1
    `[boolean, string] extends unknown[]` is true, but `unknown[] extends [boolean, string]` is false, and it is the latter test that happens with function inputs. Functions are *contravariant* in their inputs. Functions can safely choose to output something more specific than their declaration (its annotated return type is `string | number` but it only actually returns `string`s) but they cannot safely expect their inputs to be something more specific than their declarations (its annotated argument type is `string | number` but it actually only accepts `string`s). – jcalz May 15 '22 at 00:34
  • 1
    See the answer to the linked question for more information. – jcalz May 15 '22 at 00:35
  • But `any[] extends [boolean, string]` is also `false`, so it is not an answer. – Just Alex May 16 '22 at 07:13

0 Answers0