It is common to write a function where the return data type is related to the data type(s) of the parameters passed to the functions. Let’s look at an example of this:
function firstElement(arr: any[]) {
return arr[0];
}
This function will return the first element of an array. However, it uses the any
data type to allow for any type of data to be passed to it. (Notice the [], which means it’s an array, but outside of that, we have no control.)
The problem is, this means we’re no better off with a TypeScript code, as we would be with plain JavaScript. So, we can use a generic type in our function to allow us to define different types of data.
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
Notice that we use a union ( | ) to offer two types of data, the Type passed in, and if it isn’t an array, or the array has no elements.
Consider the follow examples of using the above function.
// s is of type 'string' since they are all strings
const s = firstElement(["fox", "bat", "dog"]);
// n is of type 'number' since they are all numbers
const n = firstElement([3, 5, 7]);
// u is of type undefined as there are no elements
const u = firstElement([]);
Multiple Generics
You can use your Generic multiple times in your parameter if you want. All you need to do is apply it to all the necessary parameters.
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
// this is OK because both arrays of the same type
result = combine([1,3,5], [2,4,6]);
// this is an error, because the data types of the arrays are different data types
result = combine([1,3,5], ['a','b','c']);
Multiple Generic Types
There is nothing special about the Type
word that was used in the example. i.e. it is not a keyword. That means we can use multiple generics, and give them different names if we expect them to be different data types. We also see this in other languages, like C++ and Java.
function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {
return arr.map(func);
}
Here we are using two different data types, Input and Output.
Constraints in our Generics
Sometimes we want to allow different types of data, but we need them to be with a sub-set, much like how we might logically use a Union to list a couple of data types, but we want to return the same data type. That means a union is out, and we can union within a generic. So we have to use something else – and thus we use a constraint.
With a constraint, we can force the data type we are using to have a certain property, such as length. In this case, we can force the data type to be any data type that has a length property, such as an array, or a string, but none others.
function shortest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length <= b.length) {
return a;
} else {
return b;
}
}
Generic Functions in TypeScript was originally found on Access 2 Learn
2 Comments
Comments are closed.