Learn TypeScript

Creating readonly function parameters

Creating readonly function parameters

In this lesson, we will learn how to create readonly function parameters.

Creating readonly array parameters

We are going to explore readonly parameters in the TypeScript playground.

  • Open the TypeScript playground by clicking the link below:
Open TypeScript Playground
  • Paste the code from below into the TypeScript Playground:
function doubleScores(scores: number[]) {
scores.forEach((score, i) => (scores[i] = score * 2));
return scores;
}
const billScores = [90, 65, 80];

The code contains a function that doubles the numbers in an array along with an array of numbers.

  • Let's invoke the function, passing in the array of numbers.
const doubledScores = doubleScores(billScores);
  • Output the original array as well as the new array to the console.
console.log(billScores, doubledScores);
  • Click the Run option in the TypeScript Playground and open the console.
🤔

Look at the output in the console. The items in billScores have been doubled as well as doubledScores. Why is this so?

Unintentionally mutating function parameters can cause subtle bugs. So, it would be nice if we could make a function parameter readonly.

We can make array parameters readonly by putting the readonly modifier before the array type:

arrayParameter: readonly ArrayType
  • Update doubleScores so that the scores parameter is readonly:

A type error now occurs where we mutate scores. Neat!

  • Update doubleScores so that it no longer mutates the scores parameter:
function doubleScores(scores: readonly number[]) {
return scores.map((score, i) => score * 2);
}

No type errors occur. If we rerun the code and look in the console, we can verify that billScores is not mutated.

Creating readonly object parameters

Let's explore a different function — this time, a function that has an object parameter.

  • Copy the code from below into the TypeScript Playground, overwriting the previous code:
type PersonScore = {
name: string;
score: number;
};
function doubleScore(person: PersonScore) {
person.score = person.score * 2;
return person;
}
const bill: PersonScore = {
name: "Bill",
score: 90,
};
const doubleBill = doubleScore(bill);
console.log(bill, doubleBill);

The function doubles a score property within the object parameter. The code also invokes the function and outputs the original object and the function output object.

  • Click the Run option in the TypeScript Playground and open the console.
🤔

Look at the output in the console. The score property within bill has been doubled. Why is this so?

  • We can make the person parameter readonly by using the Readonly utility type:
function doubleScore(person: Readonly<PersonScore>) {
...
}

A type error now occurs where we mutate person. Neat!

  • Update doubleScore so that it no longer mutates the person parameter:
function doubleScore(person: Readonly<PersonScore>) {
return { ...person, score: person.score * 2 };
}

No type errors occur. If we rerun the code and look in the console, we can verify that bill is not mutated.

Nice!

Summary

Making function parameters immutable helps us write pure functions and avoid subtle bugs.

Array function parameters can be made compile-time immutable by using the readonly modifier. Object parameters can be made shallow compile-time immutable by using the Readonly utility type.

In the next lesson, we will learn how to create deep immutable types.

Did you find this lesson useful?

Share this lesson on twitter
© 2023 Carl Rippon
Privacy Policy
This site uses cookies. Click here to find out more