Reputation: 36876
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.
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
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