The typescript handbook currently has nothing on arrow functions. Normal functions can be generically typed with this syntax: example:
function identity<T>(arg: T): T {
return arg;
}
What is the syntax for arrow functions?
Edit
Per @Thomas comment, in newer TS compilers, we can simply do:
const foo = <T,>(x: T) => x;
Original Answer
The full example explaining the syntax referenced by Robin... brought it home for me:
Generic functions
Something like the following works fine:
function foo<T>(x: T): T { return x; }
However using an arrow generic function will not:
const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag
Workaround: Use extends on the generic parameter to hint the compiler that it's a generic, e.g.:
const foo = <T extends unknown>(x: T) => x;
If you're in a .tsx
file you cannot just write <T>
, but this works:
const foo = <T, >(x: T) => x;
As opposed to the extends {}
hack, this hack at least preserves the intent.
const foo = <T = any,>(x: T) => x
doesn't work...
I found the example above confusing. I am using React and JSX so I think it complicated the scenario.
I got clarification from TypeScript Deep Dive, which states for arrow generics:
Workaround: Use extends on the generic parameter to hint the compiler that it's a generic, this came from a simpler example that helped me.
const identity = < T extends {} >(arg: T): T => { return arg; }
This works for me
const Generic = <T> (value: T) => {
return value;
}
.ts
file this works. Otherwise one has to extend.
The language specification says on p.64f
A construct of the form < T > ( ... ) => { ... } could be parsed as an arrow function expression with a type parameter or a type assertion applied to an arrow function with no type parameter. It is resolved as the former[..]
example:
// helper function needed because Backbone-couchdb's sync does not return a jqxhr
let fetched = <
R extends Backbone.Collection<any> >(c:R) => {
return new Promise(function (fulfill, reject) {
c.fetch({reset: true, success: fulfill, error: reject})
});
};
so late, but with ES6 no need extends it still work for me.... :)
let getArray = <T>(items: T[]): T[] => {
return new Array<T>().concat(items)
}
let myNumArr = getArray<number>([100, 200, 300]);
let myStrArr = getArray<string>(["Hello", "World"]);
myNumArr.push(1)
console.log(myNumArr)
<T, >
. as described in @Thomas comment under @jbmilgrom' answer
This works for me
const logSomething = <T>(something:T): T => {
return something;
}
while the popular answer with extends {}
works and is better than extends any
, it forces the T
to be an object
const foo = <T extends {}>(x: T) => x;
to avoid this and preserve the type-safety, you can use extends unknown
instead
const foo = <T extends unknown>(x: T) => x;
I to use this type of declaration:
const identity: { <T>(arg: T): T } = (arg) => arg;
It allows defining additional props to your function if you ever need to and in some cases, it helps keeping the function body cleaner from the generic definition.
If you don't need the additional props (namespace sort of thing), it can be simplified to:
const identity: <T>(arg: T) => T = (arg) => arg;
<T>
inside the function body, this did not work for me. Typescript tells me <T>
isn't used for the <T>
at the function definition location and tells me that it cannot find <T>
at the position where I refer to it in the function body. With the <T,>
'hack' I do not have this issue.
I know I am late to this answer. But thought of answering this in case anyone else finds it helpful. None of the answers mention how to use generics with an async
arrow function.
Here it goes :
const example = async <T> (value: T) => {
//awaiting for some Promise to resolve or reject;
const result = await randomApi.getData(value);
}
In 2021, Ts 4.3.3
const useRequest = <DataType, ErrorType>(url: string): Response<DataType, ErrorType>
=> {
...
}
Adding an example for multiple depended generic types:
This function, was converted to arrow function as the following:
http.get = function <T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R> {
config.withCredentials = true;
....
};
Notice the extends instead of the equal sign:
http.get = async <T extends any, R extends unknown = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R> => {
config.withCredentials = true;
...
};
https://i.stack.imgur.com/LuzEI.png
Using
https://i.stack.imgur.com/cTthY.png
Here I got 2 cases of arrow function with generics:
To call directly:
const foo = <T>(value: T): void => {
console.log(value);
foo('hello') // hello
}
To create a type to use later:
type TFoo<S> = (value: S) => boolean;
const foo: TFoo<number> = (value) => value>0;
console.log(foo(1)) // true
console.log(foo(-1)) // false
Hopefully this helps somewhere!
Success story sharing
const foo
? i.e.type GenericFun<T, A=T> = (payload: A) => T;
then makeconst foo: GenericFun
still generic without providing aT
type?.tsx
file (TypeScript + JSX). In a.ts
file it works fine, as you can see on the TypeScript playground.const foo = <T,>(x: T) => x;
to sidestep the JSX ambiguity.