Learn TypeScript

Using generic rest elements with tuple types

Using generic rest elements with tuple types

In this lesson, we will learn how to use generic rest elements with tuple types.

Understanding rest element types

We briefly touched on rest elements when we learned about tuples earlier in the course.

As a reminder, a rest element type is a type for a collection of tuple elements. Consider the type below:

type Scores = [string, ...number[]];

The first element in this tuple type is a string, with subsequent elements being numbers.

Using generic rest element types

A rest element type can be from a generic parameter. Let's explore this by carrying out the following steps:

  • Open the TypeScript playground by clicking the link below:
Open TypeScript Playground
  • Make sure the TypeScript version in the Playground is set to at least v4 and paste the code from below:
type NameAndThings<T extends unknown[]> = [string, ...T];
  • Add labels to the elements in the tuple as follows:
type NameAndThings<T extends unknown[]> = [name: string, ...things: T];

The labels make the structure of the tuple a little more readable.

  • Declare a variable to hold numeric scores for Bob using our NameAndThings type:
let bobScores: NameAndThings<number[]>;
  • Assign the following value to bobScores:
bobScores = ["Bob", 4, 9, 3];
🤔

Does a type error occur on this assignment?

  • Now assign another value to bobScores:
bobScores = ["Bob", 4, "9", 3];
🤔

Does a type error occur on this assignment?

  • Declare a variable to hold grades scores for Bill using our NameAndThings type. The tuple should contain a string-based name in the first element and grades in subsequent elements. The grades can be 'A', 'B', or 'C'.
  • Assign the following value to billGrades:
billGrades = ["Bill", "A", "A", "C"];
🤔

Does a type error occur on this assignment?

  • Now assign another value to billGrades:
billGrades = ["Bill", "A", "D", "C"];
🤔

Does a type error occur on this assignment?

Using generic rest element types in functions

Function parameters can be thought of as a tuple. Let's explore this in the following steps:

  • Paste the following code into the editor:
function logThings<T extends unknown[]>(name: string, ...things: T) {
console.log(things);
}

The first parameter in this function is a string.

The function also accepts a varying number of subsequent parameters that are collected into the things rest element. things is required to be a tuple of type T.

  • Call the logThings function and pass "Bob" and three numbers as parameters.
🤔

Why don't we need to pass the generic parameter explicitly?

  • Call the logThings function again as follows:
logThings("Bob", 4, "9", 3);
🤔

Does a type error occur on this function call?

  • Revise the logThings call to the following:
logThings<number[]>("Bob", 4, "9", 3);
🤔

Does a type error occur now?

Summary

Function parameters can be thought of as a tuple. Typing function parameters as a tuple allow strongly-typed functions to be created that have varying parameters.

Next up we will learn how to use the spread operator on a generic parameter.

© 2023 Carl Rippon
Privacy Policy
This site uses cookies. Click here to find out more