I can define and use a generic function like this:
const fetchData = <T>(): T[] => {
const arr: T[] = []
// if stuff push to arr
return arr
}
const emptyStringArray = fetchData<string>();
However, in my actual scenario, I have a lot of params and would like to separate out the typings and function assignment.
I've attempted to write like this:
type IFetchData = <T>() => T[]
const fetchData2: IFetchData = () => {
const arr: T[] = []
// if stuff push to arr
return arr
}
const emptyStringArray = fetchData2<string>();
However, now the function definition doesn't recognize the T
as an available type.
Cannot find name 'T'.
I've tried a lot of different configurations on where to put the <T>
, but nothing seems to work - any ideas?
Demo in TS Playground
Related Questions
- How to create a generic type alias for a generic function?
- Generic function type alias
- Function with Generic Return Type
- Type of generic function
CodePudding user response:
IFetchData
is doing the return typing for you, so it should work to omit the generic from the fetchData2
function return. Does the following work?
type IFetchData = <T>() => T[]
const fetchData2: IFetchData = () => {
return [];
}
CodePudding user response:
First of all, this function:
const fetchData = <T,>(): T[] => {
const arr: T[] = []
arr.push(2) // error
arr.push('str') // error
return arr
}
is hard to use.
Since non of your arguments are not related to T
, TS will not allow you to push
any value to the arr
. Of course, you can use type assertion as
, but it is very unsafe:
const fetchData = <T,>(): T[] => {
const arr: T[] = []
arr.push('str' as any as T) // error
return arr
}
const emptyStringArray = fetchData<number>(); // number[]
emptyStringArray[0].toExponential() // runtime error
Related question/answer, my article
The answer is easy and simple: it is impossible in this case to separate T
from function definition without workarounds.
Here you have simplest way:
const fetchData = <T,>() => {
const arr: T[] = []
return arr
}
However, if you want to mutate your array inside fetchData
, this function signature is not useful. This function is not allowed to do anything with arr
. All you can do is to return arr
without any mutations.
In order to mutate this list, you need create higher order function and during calling fetchData
provide explicit generic argument:
type FetchData = <T>() => T[]
const fetchData: FetchData = () => []
const higherOrder = <T,>(elem: T) => {
const arr = fetchData<T>();
arr.push(elem)
return arr
}
const test = higherOrder('str'); // ok, string[]
const test2 = higherOrder(42); // ok, number[]
CodePudding user response:
Could you try it?
type IFetchData = <T>() => T[]
const fetchData2: IFetchData = <T>() => {
return [];
}