TypeScript Basics: Generic Function Types
Welcome to the Generic Function Types lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
We've already seen generic functions.
>
function first<T>(elements: Array<T>): T {return elements[0];}- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
first<boolean>([true, false, true]);Result:
true
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
first<string>(['a', 'b', 'c']);Result:
'a'
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
first<number>([true, false, true]);Result:
type error: Type 'boolean' is not assignable to type 'number'.
Every function has a type, so generic functions must have types too. Currently, TypeScript is inferring the type of our function automatically. However, we can write its type down if we want to.
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
type First<T> = (elements: Array<T>) => T; Make sure to compare that type to the original
firstfunction. The type says: "First is a function type that takes an array of things. It returns one of those things." The "things" part of the type is written as<T>.We can use this type to narrow our
firstfunction, just as we've narrowed objects previously. We'll narrow it to a version that only works on strings.- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
const firstString: First<string> = first; - Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
firstString(['a', 'b']);Result:
'a'
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
firstString([1, 2]);Result:
type error: Type 'number' is not assignable to type 'string'.
When this code executes, the compiled
firstStringfunction will be identical to our very first generic version. Narrowing only affects the types.Why would we want to add code that doesn't change the compiled program? For the same reason that we use types in any other situation: to tell the compiler how to reject incorrect programs.
Maybe we have a part of the system where we want the first number in an array of numbers. But we also want to make sure that no strings sneak in. Why not tell the type system that it's a
First<number>? That way it can keep us honest!