ZiiMakc
ZiiMakc

Reputation: 36876

How to properly extend generic return type of array

I have a database transaction function that can make multiple queries and return result in format [resultQuery1, resultQuery2 and so on for each query]. I'm not sure how can i supply a expected return type to this generic function.

Playground.

Example:

type Author = string
type Book = { id: number }
type PossibleArrayResponseOfTypes = [Author, Book] // or [Author, Book, and more]


async function AsyncFN() {
  // T is always an array of expected results  
  const transaction = async <T extends any[] = any[]>(): Promise<null | T> => {
   return ['str', {id: 1}]
  }

  const res = <PossibleArrayResponseOfTypes>await transaction()
}

Error:

Type '(string | { id: number; })[]' is not assignable to type 'T'. '(string | { id: number; })[]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'any[]'.

Upvotes: 2

Views: 381

Answers (1)

Thomas
Thomas

Reputation: 181795

No need to specify any of those types; just let type inference do its thing:

async function AsyncFN() {
  // T is always an array of expected results  
  const transaction = async() => {
   return ['str', {id: 1}]
  }

  const res = await transaction()
}

With --noImplicityAny and --strictNullChecks this is just as type-safe as the verbose version.

In general, you should rarely need casts, and the use of casts should be a big red flag. TypeScript's type system is very powerful, and it's almost always possible to express types statically in a way that correctly represents what happens at runtime.


Here's what the error message is trying to tell you. The anonymous async function is generic, with a type argument T that must be a subtype of any[], and it returns a value of this type T. The function must, under all circumstances, honour this contract. Let's simplify it a bit without losing the essence:

function myFunc<T extends any[]>(): T {
  return ['str']
}

Someone could call this function as:

myFunc<number[]>()

which must return an object of type number[]. But the body of the function doesn't do that; it only ever returns a string[].

Upvotes: 1

Related Questions