Last updated: Feb 29, 2024
Reading timeยท3 min
.tsx
files, use a trailing commaYou can use a generic in an arrow function by setting it right before the function's parameters.
The generic can be passed when the function is invoked.
const returnInArray = <T,>(value: T): T[] => { return [value]; }; const strArray = returnInArray<string>('bobbyhadz.com'); const numArray = returnInArray<number>(100);
Generics allow us to pass types as a variable to functions and classes.
The syntax for calling a function that has a generic is the same - it's passed right before the function's arguments.
Note that we didn't have to explicitly provide the generic when calling the function.
In this situation, TypeScript would be able to infer the type of the generic based on the type of the passed-in argument.
const returnInArray = <T,>(value: T): T[] => { return [value]; }; // ๐๏ธ const strArray: string[] const strArray = returnInArray('bobbyhadz.com'); // ๐๏ธ const numArray: number[] const numArray = returnInArray(100);
We can apply constraints around generics to only allow certain types to be passed.
type CanRun = { run(): void; }; // ๐๏ธ Can only be called with an object that has run() method const callRun = <T extends CanRun>(obj: T) => { obj.run(); }; // ๐๏ธ the animal runs callRun({ run: () => console.log('the animal runs') }); class Dog { run() { console.log('the dog runs'); } } callRun(new Dog()); // ๐๏ธ the dog runs
The callRun()
arrow function can only be called with an object that has a
property run
that is a function with a
return type of void
.
If we try to call the function with a value that doesn't satisfy the CanRun
type, we would get an error.
type CanRun = { run(): void; }; const callRun = <T extends CanRun>(obj: T) => { obj.run(); }; // โ๏ธ Argument of type 'number' is not assignable // to parameter of type 'CanRun'.ts(2345) callRun(100);
This pattern is very commonly used when you need a guarantee that a function can only be called with an object that contains certain properties.
The object could be of multiple types, but as long as it contains the specified properties, it can be passed as an argument to the function.
class Shark { swim() { console.log('The shark swims'); } } class Dolphin { swim() { console.log('The dolphin swims'); } } interface CanSwim { swim(): void; } const callSwim = <T extends CanSwim>(obj: T): void => { obj.swim(); }; callSwim<Dolphin>(new Dolphin()); callSwim<Shark>(new Shark());
The callSwim
function takes an object parameter and calls the swim
method on
it.
The function uses a constraint to make sure that it only gets passed objects
that contain a swim
property of type function.
You can also use generics in arrow functions in classes.
class GenericArray { public arr: (string | number)[] = []; insert = <T extends string | number>(el: T): void => { this.arr.push(el); }; print = (): void => { console.log(this.arr); }; } const ga1 = new GenericArray(); ga1.insert<string>('a'); ga1.insert<number>(1); ga1.print(); // ๐๏ธ ['a', 1] // โ๏ธ Argument of type '{ hello: string; }' is not assignable // to parameter of type 'string | number'.ts(2345) ga1.insert({ hello: 'world' });
The insert
class method can either be passed a string or a number.
.tsx
files, use a trailing commaNotice that we used a trailing comma after the T
type in the generic.
const returnInArray = <T,>(value: T): T[] => { return [value]; }; const strArray = returnInArray<string>('bobbyhadz.com'); const numArray = returnInArray<number>(100);
Newer TypeScript compilers support a trailing comma after the last type in the generic.
This is necessary for .tsx
files, otherwise, you'd get syntactical errors.
If you have multiple types, you don't have to use a trailing comma in .tsx
files, e.g. <T,Y>
works.
Alternatively, you can extend an empty object if you still get syntactical
errors in .tsx
files.`
const returnInArray = <T extends unknown>(value: T): T[] => { return [value]; }; const strArray = returnInArray<string>('bobbyhadz.com'); const numArray = returnInArray<number>(100);
The T extends unknown
constraint does nothing and is only necessary if you get
syntactical errors when working in .tsx
files.
I've also written a detailed article on how to set the return type of an arrow function.
If you need to pass a function as a parameter, check out the following article.
You can learn more about the related topics by checking out the following tutorials: