0

I've got an array of the following types:

myList = [
 listOfString: Parser<string[], string, any>
 stringThing: Parser<string, string, any>
]

and typesript marks myList of type (Parser<string[], string, any> | Parser<string, string, any>)[]

Is there a way to convert this into Parser<string | string[], string, any> by default?

Alternativly, when passing this to a function that looks like

myFunc<T>(list: Parser<T>[]): Parser<T>

is there a way to allow this type of array and make it that myFunc returns Parser<string | string[], string, any>?

3
  • Please put your code in Playground Commented Jul 3, 2021 at 10:01
  • Why don't you just explicitly declare the type of myList? myList:Parser<string[]|string, string, any>[] Commented Jul 3, 2021 at 10:19
  • Broadly speaking Array<A>|Array<B> is not the same type as Array<A|B> so converting one to the other would be wrong. Commented Jul 3, 2021 at 10:39

1 Answer 1

3

Is there a way to convert this into Parser<string | string[], string, any> [...]?

T<string> | T<string[]> and T<string | string[]> are not equivalent types in the general case.

Consider as an example

type T<U> = (u: U) => U;

Now T<string> | T<string[]> is either a function taking a string, or a function taking an array of strings. In either case the function's parameter is only one of those two types, and you can only call it with an argument of that type. If you (can) call it with a string, you can't call it with an array of strings, and it must also return a string.

On the other hand, T<string | string[]> describes a function whose parameter is a string or an array of strings, meaning that for every single invocation you can choose which one you pass. It would also be possible that you call it with a string but the function returns an array of strings.

With a concrete example, (u: string) => u would satisfy the first type, but isn't assignable to the second:

// OK
const test1: T<string> | T<string[]> = (u: string) => u;

// Error
const test2: T<string | string[]> = (u: string) => u;

Similarly, (u: string | string[]) => u has the opposite effect:

// Error
const test3: T<string> | T<string[]> = (u: string | string[]) => u;

// OK
const test4: T<string | string[]> = (u: string | string[]) => u;
Sign up to request clarification or add additional context in comments.

1 Comment

For an example without contravariance, type Thing<T> = {a: T, b: T} would allow {a: string, b: string[]} to be of type Thing<string | string[]> but not of type Thing<string> | Thing<string[]>.

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.