3

Need help understanding how the below piece of code works.

function concatFun<T extends any[], U extends any[]>(
  arg1: T[],
  arg2: U[]
): [...T, ...U] {
  const newArr = [...arg1, ...arg2]; // (T | U)[]
  return newArr; // error Type '(T | U)[]' is not assignable to type '[...T, ...U]'.
                 // Target requires 2 element(s) but source may have fewer.
}

I wanted the return type to be [...T, ...U], but the return type is (T | U)[].

2 Answers 2

1

FIXED You need to infer literal type of provided arguments

type Json =
  | null
  | string
  | number
  | boolean
  | Array<JSON>
  | {
    [prop: string]: Json
  }

function concatFun<
  Fst extends Json, T extends Fst[],
  Scd extends Json, U extends Scd[]>(
    arg1: [...T],
    arg2: [...U]
  ): [...T, ...U] {
  return [...arg1, ...arg2]

}

concatFun([1, 2, 3], [4, 5, 6]) // [1, 2, 3, 4, 5, 6]

Playground

Update

function concatFun<
  Fst extends Json, T extends Fst[],
  Scd extends Json, U extends Scd[]>(
    arg1: [...T],
    arg2: [...U]
  ) {
  const foo: [...T, ...U] = [...arg1, ...arg2]
  return foo
}
}

You can help TS to infer concatenated array. To be honest, I'm not sure how TS resolves it unfer the hood. But error message is pretty intuitive if you will et rid of explicit type [...T, ...U] from foo

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

2 Comments

Thanks for the answer. It way more neat. However, I still have hard time understanding, why is TS complain when i use assign spread and then return. Playground
@nitte93 made small update
1

This is probably what you meant:

function concat<T extends readonly any[], U extends readonly any[]>(
  arg1: T,
  arg2: U,
): [...T, ...U] {
  return [...arg1, ...arg2]
}

T[] means "array of Ts", but not "T which is an array".

See this TypeScript playground.

2 Comments

That definitely was a mistake and thanks for pointing it out. However, why is there a complain when I assign spread to a const and then return. TypeScript Playground
Hm, I'm not sure. Perhaps it has to do with the ability to mutate the array afterwards? If you do const newArr = [...arg1, ...arg2] as const, newArr does get inferred as readonly [...T, ...U]. Perhaps this SO question is related?

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.