If you have a Python background, you must have come across one of the four main built-in data types called Tuples used to store multiple items in a single variable. Previously, we didn’t have tuples in JavaScript, and programmers had to use various methods like array destructuring to play the role of tuples. But that was before the ECMAScript proposal (by Robin Ricard and Rick Button) that introduced two new compound primitive values in JavaScript:
- Records
- Tuples
This post will primarily focus on the latter – JavaScript tuples.
In JavaScript, tuples are a bit like arrays since we use square brackets to define them and can also use various array methods. However, unlike arrays, they have a pre-defined length, and the types of data in a tuple are fixed once we have initialized it. In other words, a tuple in JavaScript is a typed array.
In this post, we will have an in-depth look at JavaScript Tuples and how to use them in our applications. Let’s dive in.
Table of Contents
Support for Tuples
As stated above, Tuples are still a new primitive type in JavaScript introduced by the ECMAScript proposal. This proposal is currently in Stage 2 at the moment of this writing, which means people have looked at it and seen it’s a topic worth debating. At this point, developers also try to figure out the syntax and how the tuples would work. Unfortunately, Tuples won’t be introduced into browsers and Javascript frameworks like NodeJS until they reach Stage 3 (Candidate) or Stage 4.
Using Polyfill and Playground
Since we are still in Stage 2, we can use tuples in our applications only with Babel by using this polyfill. However, if you simply want to practice using Records and tuples without the hassle of setting up the environment, feel free to use the easy-to-use REPL – Rick Button – Tuple and Record playground. We will use this playground for this particular post.
Creating a Tuple in JavaScript
Tuples introduced a new primitive type in JavaScript, which essentially follows the array syntax. There is only one difference. When declaring a tuple, you must prefix the square brackets with a ‘#’ (hash) symbol. Look at the code below, which shows the difference between an array and a tuple.
let myArray = [12, 23, "yellow"] //this is an Array
let myTuple = #[4, 5, "black"] // this is a Tuple. You can see the '#' in front of the square brackets.
log("isArray", Array.isArray(myArray))
//Returns [“isArray”, true]
log("isTuple", Tuple.isTuple(myTuple))
//Returns [“isTuple”, true]
As you can see in the code snippet above, the syntax of tuples is quite similar to that of arrays, with the only difference being the ‘#’ sign.
You will also notice that although we said tuples are primitive data types, we are using the Tuple.isTuple to check the type of our tuple variable instead of the typeof() keyword. That’s because typeof() is still an unsupported feature in the Babel polyfill we are using and will return an incorrect value.
Tuples are Primitives
JavaScript stores data either as ‘primitive types’ or ‘reference types.’ Primitive types are simple atomic pieces that are always saved and accessed by the variable’s value and not as a reference to an object. There are six main primitive types in JavaScript: undefined, null, boolean, symbol, string, and number. With the ECMAScript proposal, we will now have more primitives, including records and tuples.
Therefore, when we use the typeof keyword to check the type of our tuple variable, it should return a tuple as shown in the code snippet below.
typeof #['a', 'b']
//returns 'tuple'
let myTuple = #["Bob","Jane"]
typeof(myTuple)
//returns 'tuple'
Reference types are not simple atomic values, but objects made up of multiple properties assigned to them. They are stored as a reference in memory and not as independent values assigned to variables. The three main reference types in JavaScript are arrays, objects, and functions.
Tuples are Deeply Immutable
In many programming languages, we have both mutable and immutable values. Mutable values are those that can be changed or a new property can be added to them. On the other hand, immutable values in JavaScript cannot be changed or have anything added to them. They can only be reassigned. All primitive types in JavaScript are immutable. Let’s understand this by looking at strings and arrays.
//We will create two String variables (nameOne and nameTwo)
let nameOne = "John";
let nameTwo = nameOne;
console.log(nameOne)
//returns 'John'
console.log(nameTwo)
//returns 'John'
//Here we are re-assigning the nameTwo variable to ‘Janedoe’
nameTwo = "Janedoe"
//When we log the output of the two variables, only nameTwo changed.
console.log(nameOne)
//returns 'John'
console.log(nameTwo)
//returns 'Janedoe'
From the code snippet above, you notice that after we re-assigned the variable “nameTwo,” the value of variable “nameOne” did not change and instead a new string was created. Now let’s look at arrays that are reference types and are mutable.
let arrayOne = [12, 13, 14]
Let arrayTwo = arrayOne
console.log(arrayOne);
//returns [12,13,14]
console.log(arrayTwo)
//returns [12,13,14]
//Let's re-assign an index in arrayTwo
arrayTwo[0] = "yellow"
console.log(arrayOne);
//returns ["Yellow",13,14]
console.log(arrayTwo)
//returns ["Yellow",13,14]
From the code snippet, you notice that when we re-assigned the index[0] in arrayTwo, the values in arrayOne also changed since the two variables were referencing one object.
So, why are tuples deeply immutable? That’s mainly because tuples by themselves are immutable and they can only hold primitive types, other tuples or records (which are also immutable). A tuple cannot hold any reference types, such as arrays or objects. However, the opposite is true. You can use an array or object to hold a tuple.
// This is Okay
const tupleOne = #[10, 20, "Johndoe",]
//ERROR: Sets an Array
const tupleTwo = #[10,22,"Janedoe",[12,4,5]]
//ERROR: Sets an Object
const tupleThree = [new Date()]
//This is Okay.
const arrayOne = [12, 13, 14, #[12, 13, “Yellow”]]
console.log(arrayOne[3])
//returns tuple {12,13,”Yellow”}
//Error: Tuples can’t be changed at any level
const tupleOne[0] = 23
Lastly, tuples cannot have holes of unset values.
//This will raise an Error: Unexpected token ','
Let tupOne = #[2,,,"Green",5]
Comparing by Value
If there is one hurdle that most newbie JavaScript developers face is comparing reference types. Let’s look at the code below which tries to compare arrays and objects.
//Compare Objects
console.log({a:12, b:24} === {a:12,b:24})
//returns false
//Compare Arrays
console.log([12,13,14]===[12,13,14])
//returns false
Why are we getting a ‘ False ’ yet the array and the object have the same values? Reference types like Arrays and Objects in JavaScript are compared by the reference or address in memory where the value is stored. And of course, we cannot store two different variables in the same memory address.
Unlike arrays, tuples are compared by their values.
console.log(#[12,13,14] === #[12,13,14])
//returns true
console.log(#[12,13,15] === #[20,30,40])
//returns false
Convert Arrays to Tuples
You can use the Tuple.from() method to create a tuple from an existing array.
const arrayOne = [12,13,14]
const tupleOne = Tuple.from(arrayOne)
const tupleTwo = Tuple.from([12,24,35])
Caveat: However, there is a catch! If any value in the array is of non-primitive type, you will get an error. That’s because tuples in JavaScript can only hold primitive types. See the code snippet below.
const arrayOne = [12,13,[25,34]]
//This will raise an Error
const tupOne = Tuple.from(arrayOne)
//This will raise Error
const tupTwo = Tuple.from([1,2,[“a”,”b”]])
Convert Tuples to Arrays
Likewise, you can use the Array.from() method to convert tuples to arrays.
let tupOne = #[12,13]
log(Array.from(tupOne))
//returns [12,13]
JSON and Tuples
The JSON.stringify() method is used to convert arrays and objects to JSON strings and treats tuples like arrays. See the code snippet below.
const tupOne = #[12,13,#[12,13]]
const a = JSON.stringify(tupOne)
console.log(a)
//returns "[12,13,[12,13]]"
const tupTwo = #[12,13]
console.log(tupTwo)
//returns # "[12,13]"
Conclusion
That’s it! Up to this point, I believe you now have a good understanding of what tuples are in JavaScript and how you can use them in your program. Other than the few examples we have looked at above, you can use tuples in loops and functions as you would with arrays. As of writing this post, tuples are still a new feature and not widely supported. You will need the Babel polyfill to use them.
Have you already worked with tuples?
Please, let us know your thoughts by replying on Twitter of Become A Better Programmer.