ES6 Destructuring in TypeScript

Riley Hilliard
4 min readApr 15, 2019

--

Destructuring is one of the more powerful features added to ES6 that has added elegant syntactic sugar to JavaScript, so one of the first things I was curious about was how TypeScript might interact with destructuring. To my surprise, it was hard to come across any good explanations about this subject, so I set off this piece together all the bits I could find. What I have come to learn is that TypeScript and destructuring can seem to conflict at times, but if you learn TypeScripts flavor of destructuring you can continue to use this much-appreciated feature of ES6 while adding the strict typing stability of TypeScript.

If you are new to TypeScript, it is a superset of JavaScript that introduces the concept of strict typing. It brings the stability of a strictly typed language to the defacto programming language of the web: JavaScript!

TypeScript was first introduced in 2012 and is not that new of a “language”, but over the last couple of years, TypeScript has grown significantly in popularity. In GitHub’s 2019 edition of “State of the Octoverse”, TypeScript climbed from outside the “Top 10” languages to 7th on the list of active repositories. That is a very impressive year-over-year change. If you haven’t tried TypeScript, now is the time to start getting familiar.

Functional Destructuring

Functional destructuring is where a function takes an object argument and destructures the object properties into variables that can be used within the function.

If you look at how TypeScript defines property types within functions you may think that the TypeScript equivalent of a functional object destructure might just define the variable type after the destructed variable, however, this doesn’t work because ES6 destructuring variable name reassignment clashes with what might appear to be TypeScripts variable-type decoration syntax. The result of running the code in this example would be that the first and last destructured variables get reassigned to the variable string.

The correct way to handle TypeScript functional destructuring is to define an interface and reference the interface after the destructure. TypeScript is then able to understand that the function takes an object argument that is of the shape of the Person interface and destructuring occurs as you would expect it to in ES6.

This example shows the power of functional Array and Object destructuring together. In this example, helloFirstPerson() takes an array of Person objects and uses Array destructuring to access the first item of the array. It then destructures the persons first and last name properties into constants that are used later in the function. TypeScript asserts that the argument of the helloFirstPerson() function is an array of Person objects that contain first and last properties that are strings. Now if the object structure of the people array changes to be something that our function does not expect, we will be alerted about it before we even run our code 😍!

Class Constructor Destructuring

What about a more complicated example, such as a JavaScript class instance? Let’s use a Person as an example for our class. It is common for Person classes to ingest first and last name properties, and supply a fullName getter that returns the instances fullName. Without TypeScript, the Person class could have almost any shape of instantiation argument supplied which could lead to bugs down the road. To ensure we don’t break our fullName generator we will use TypeScript to enforce that the Person class is instantiated with mandatory first and last name properties. Strict object shape enforcement is especially important if we wish to leverage destructuring within the class constructor. If an argument is not of the shape that we expect, we could start encountering destructuring errors around accessing properties from non-object argument types. With TypeScript, we can define the required class instantiation schema, then destruct the properties we wish to import into the class, that way we always know that the class constructor has all the required structures we expect. If our incoming shape does not match the expectations of our Person class, TypeScript will raise an error alerting us that we are missing required arguments. The result is a much more stable code structure that is harder to break in the future. Nice!

--

--