Comp 110 Generic Functions

When do we use generic functions?

When functions do the same thing but have different parameter types or return types, we don't have to continue making new versions of the same function just to deal with this. We can use generic functions in these situations so that we only have to write out the implementation once and it'll work for different types of parameter and return types. Here's the general form for making a generic function:

let functionName = <T> (parameter0: *type*, parameter1: *type*): *type* => // ...

Here, the diamond syntax <T> indicates that our function will be generic for any type, T. We could use a different letter if we wanted, but we'll just stick with T. We can use this T type wherever we use any other *type*. Here's one way that might look:

let functionName = <T> (parameter0: T, parameter1: number): boolean => // ...

We call generic functions the same way we call normal functions, making sure the arguments we pass in match the types of the parameters we specify when we define the function. So, if a parameter has the generic type T in the definition, when we call the function the argument we give should be the specific type we'd want to use in that instance.

Example

If we wanted to, we could make a function to tell us whether two things are equal. Here it is for testing two strings:

let eq0 = (i: string, j: string): boolean => {
    if (i === j) {
        return true;
    } else {
        return false;
    }
};

And here it is for testing two numbers:

let eq1 = (k: number, l: number): boolean => {
    if (k === l) {
        return true;
    } else {
        return false;
    }
};

We could do more examples of these, but they work the same way. The important part, and the only part that changes, is in regards to the types of the parameters. We really want to do this for any types, not just string or number, but we need to be sure both parameters are the same type. Here's how we'd accomplish all this with a generic function, and some examples of how to call the generic function:

let equals = <T> (item0: T, item1: T): boolean => {
    if (item0 === item1) {
        return true;
    } else {
        return false;
    }
};
// now to try it out:
equals("testing", "testing"); // true
equals(1, 23); // false
equals(4, "toby"); // invalid function call-both arguments must be of the same type!