JavaScript and TypeScript Tips

Spreading, Resting, and Renaming Properties in TypeScript

Tod Gentille
Level Up Coding
Published in
4 min readFeb 14, 2021

--

When you need a new object that is a close relation to an existing object but one or more of the property names must change.

Android “rest”ing against fresh batteries with legs “spread” out.
Am I resting or spreading out?

I first saw this technique in this excellent post by Joel Thoms. That article has a collection of tips. I just wanted to focus on this one technique, and provide a more robust explanation.

Real-World Need

While my example code is very slimmed down this technique did have roots in a real-world need. We were writing an API call to return a single object that we wanted to construct from some existing objects. The problem we had is that one recalcitrant property from one of the objects needed to be renamed.

For this discussion, assume we have an object that conforms to the following interface:

interface with two string properties, one named `a` and one named `z`.
object’s interface

and instead of a property with the name z we need a property named zed we can use this simple fat arrow function to accomplish that:

Two different operators that look the same

This one line of code contains a lot of buzzwords, so let’s walk through this. We are defining a function named renameZed it takes a single parameter that is an object. The parameter is using “de-structuring” to separate that argument into two pieces. The first de-structured item is peeling the property z off of the object. The second de-structured item is using the “rest” operator ① to get the remaining properties into an object named remainder. I have always found the name “rest” confusing here due to the homonymic collisions with the REST acronym and the verb “rest”. I used the variable name remainder to make it clearer that “rest” means “the rest of the stuff”.

After the fat arrow we need a set of parentheses, since we aren’t using the “return” keyword and braces. We start our return object with a pair of braces and specify the first property as zed. The original object’s z property value is assigned to to zed. Next, the “spread” operator ② is used to add back all of the remaining properties from the original object. We get back our desired object that conforms to this interface:

interface that replaces z with zed
the interface for the desired final object

A test for this code could look like this:

create sample Letters object, call the renameZed() function and test the return value conforms to the expected result
unit test for renameZed() function

The only thing missing now are the types. While I could have just created the interface FinalLettersas shown above, this example is much simpler than a typical object and even when creating types I want to be as DRY as possible.

Create RenamedZed type that omits the letter z from Letters and adds the zed string property to the type
Create a type named RenamedZed for our final object

Here I’m creating the type RenamedZed and specifying that it has all the properties of the Letters interface EXCEPT for the z property. The TypeScript utility Omit does the job for that. Then I use & to combine the subset of Letters’ properties with my new zed property to form an Intersection Type. If you are confused by why this is an intersection type and not a union type, this article may help some. My suggestion is to just focus more on the fact that the &operator combines the two sets of properties together and worry about set theory semantics later.

If you find you not only need to rename properties but remove one or more properties, this story now has a second chapter.

The code shown in this article is available in GitHub.

There are more JavaScript and Typescript tip articles.

Code in peace.

--

--

Pluralsight author & software developer since 1980. Mostly tech articles. Love fountain pens. Opinions expressed here are my own. https://gentille.us/subscribe