Nuevos tipos de datos en Javascript Records & Tuples
Tags: javascript, webdev, node
Published: 2021-01-02 18:35:55

¡Hola! En este post hablare sobre las **nuevas características que serán introducidas al lenguaje JavaScript**. En especial sobre los nuevos tipos de datos “Record & Tuple” [propuesto](https://github.com/tc39/proposal-record-tuple) en el ECMAScript por Robin Ricard y Rick Button, en estos momentos se encuentran en la [fase 2](https://twitter.com/robpalmer2/status/1286040041089904640) (2021-01-01) sin embargo pronto cambiara. Esta feature incluye agregar dos tipos de valores primitivos al lenguaje:
* Records (similar a un objeto).
* Tuplas (similar a un array).

# Syntaxis

La sintaxis es similar a los conocidos arreglos y objetos con una sutil diferencia, una almohadilla o signo de hash (#) al comienzo.

```javascript
const person = #{
  name: "Brian",
  lastName: "Santeliz"
}

const lenguages = #["Javascript", "Python", "Haskell", "Rust"]
```
# Características
De principio no parece nada especial, sin embargo tiene cosas muy interesantes. Te comentare alguna de las características de estos nuevos tipos de datos. 

### Inmutabilidad
 Estos nuevos tipos de datos son inmutables, similar a lo que hace el método `object.freeze()` con la diferencia de que una vez definido el Record o la Tuple no se podrán cambiar. Esto puede ser muy útil cuando se trabajan con librerías o frameworks que usan el principio de la inmutabilidad como React, además no tendremos que usar otras librerías de terceros como ImmutableJS para realizar estas operaciones.

```javascript
const person = #{
  name: "Brian",
  lastName: "Santeliz"
}
person.age = "20" // Error
const lenguages = #["Javascript", "Python", "Haskell", "Rust"]
lenguages[0] = "Php" // Error
```
Estos tipos de datos pueden anidarse entre Records/Tuples y aplican las mismos principios de inmutabilidad.
```javascript
const hero = #{
  name: "Iron Man",
  movies: #["Avengers", "Civil War", "Avengers: End Game"]
}
const lenguages = # ["Python", "Php", #{name:"JavaScript", creator:"Brendan Eich"}]
```
### Igualdad


Una de las características que más me gustan y estoy seguro que otros desarrolladores también, es la capacidad de poder comparar records y tuples por su **valor y no por su referencia**. Veamos un ejemplo.
 ```javascript
const obj = {name:"Hello"};
const obj2 = {name:"Hello"};

obj === obj2 //false
 ```
Aunque estoy comparando dos objetos que son iguales (a excepción del nombre) la comparación devuelve false, esto sucede porque Javascript compara sus referencias y no su valor, cada vez que creas un objeto este tendrá una referencia distinta. Una solución para esto seria, usando el método de `JSON.stringify()`.
 ```javascript
const obj = {name:"Hello"};
const obj2 = {name:"Hello"};

JSON.stringify(obj) === JSON.stringify(obj2) 
//true
 ```
Sin embargo este método tiene algunos problemas importantes y no es una forma segura y rápida  de resolverlo. La buena noticia es que con  **los Records & Tuples no es necesario** ya que estos comparan por el valor y no por su referencia.
 ```javascript
const obj = #{name:"Hello"};
const obj2 = #{name:"Hello"};

obj === obj2 //true

const colors = #["red","black","green", "blue"]

colors === #["red","black","green", "blue"]
  //true
 ```
Genial! incluso con records/tuples anidados.

```javascript
const lenguages = #[ "Php", #{name:"JavaScript", creator:"Brendan Eich"}]
lenguages === #["Php", #{name:"JavaScript", creator:"Brendan Eich"}] 
//true
```
Como mencione anteriormente Los Records y Tuples son datos primitivos en JavaScript, esto se puede comprobar usando la sentencia de `typeof`.

```javascript
 typeof #{a: 2, y: 3}
// "record"
typeof #[4,5,4]
//"tuple"
```
### Compatibilidad con propiedades y métodos
Podemos utilizar los métodos que ya conocemos tanto para arreglo como para objetos. Destructuring, Spread & Rest operator, Higher order functions.

```javascript
const hero = #{
name:"Iron Man ",
creator:"Marvel",
power:"1200"
}
//Destructuring & Rest operator.
const {name:newName, ...others} = hero;
console.log(others)
//{creator: "Marvel", power: "1200"}
const age = 34
const newHero = #{
...others, //syntax spread
age, //short notation
name:"Cap America"
};

const colors = #["yellow", "blue", "red"];
//filter method
const redColor = colors.filter((color)=>color === "red");
console.log(redColor)
//#["red"]
``` 
### Trabajando con los métodos JSON

Algo que hay que tener en cuenta es que `JSON.stringify()` trata los Records como objetos y las Tuples como array de manera recursiva. El metodo `JSON.parseImmutable()` funciona como `JSON.parse()` pero devuelve Records en lugar de objetos y Tuples en lugar de array nuevamente de manera recursiva.

```javascript
const recordExample = JSON.parseImmutable('{"x":"Hello","y":["Banana","Apple"]}');
console.log(recordExample);
// #{x: "Hello", y: #["Banana", "Apple"]}

const objExample = JSON.stringify(recordExample);
console.log(objExample);
// "{x: "Hello", y: ["Banana", "Apple"]}"
```

# Consideraciones 
Estos nuevos tipos de datos tienen ciertas restricciones que debemos tener en cuenta, alguna de ella son:
* Records:
 * Las key deben ser strings.
 * Los valores deben ser primitivos.
* Tuples.
 * Los elementos deben ser primitivos (no podemos incluir funciones por ejemplo).

Alguno de estos errores en código serian los siguientes:
```javascript

//Error, no se pueden tener objetos.
const errorRecordObj = #{
  obj: {
    a: "i'm an object"
  },
};

//Error, no se pueden tener funciones.
const errorRecordFunction = #{
  example: () => alert("Hello World!")
};

//Ningún otro dato que no se un primitivo.
const errorRecordDate = #{
  date: new Date(),
};

const errorRecordClass = #{
  class: new Car(),
};

const errorTupleClass = #[new Car()];

const errorRecordSymbol = #{ [Symbol()]: #{} }; 
```

# Conclusión 
Para finalizar esto post quiero hablarte de los pros y contras que pude traer la nueva sintaxis, aunque en realidad son más los puntos positivos.

* **Ventajas**: **La nueva sintaxis es precisa**. Es fácil de recordar y no tiene mucha diferencia con los objetos y arreglo, además de las ventajas de comparación por valores y la inmutabilidad.

* **Desventaja**: Una desventaja que le encuentro podría ser que el uso de el carácter alfanumérico **(#)**, puede tender a errores de sintaxis si no se usa la forma correcta. Esta sintaxis también es usada en [campos privados de clases](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Classes/Private_class_fields). 

Eso es todo lo que quería compartirles, si tienes algún aporte o duda puedes comentarla. Puedes ir al [Playground](https://rickbutton.github.io/record-tuple-playground/#eyJjb250ZW50IjoiLy9FeGFtcGxlIDFcbmNvbnN0IG9iaiA9ICN7bmFtZTpcIkhlbGxvXCJ9O1xuY29uc3Qgb2JqMiA9ICN7bmFtZTpcIkhlbGxvXCJ9O1xuXG5vYmogPT09IG9iajIgLy90cnVlXG5cbmNvbnN0IGNvbG9ycyA9ICNbXCJyZWRcIixcImJsYWNrXCIsXCJncmVlblwiLCBcImJsdWVcIl1cblxuY29uc29sZS5sb2coY29sb3JzID09PSAjW1wicmVkXCIsXCJibGFja1wiLFwiZ3JlZW5cIiwgXCJibHVlXCJdKVxuICAvL3RydWVcblxuXG4vL0V4YW1wbGUgMlxuY29uc3QgbGVuZ3VhZ2VzID0gI1sgXCJQaHBcIiwgI3tuYW1lOlwiSmF2YVNjcmlwdFwiLCBjcmVhdG9yOlwiQnJlbmRhbiBFaWNoXCJ9XVxuY29uc29sZS5sb2cobGVuZ3VhZ2VzID09PSAjW1wiUGhwXCIsICN7bmFtZTpcIkphdmFTY3JpcHRcIiwgY3JlYXRvcjpcIkJyZW5kYW4gRWljaFwifV0pXG4vL3RydWVcblxuLy9FeGFtcGxlIDNcbmNvbnN0IGhlcm8gPSAje1xubmFtZTpcIklyb24gTWFuIFwiLFxuY3JlYXRvcjpcIk1hcnZlbFwiLFxucG93ZXI6XCIxMjAwXCJcbn1cbmNvbnN0IHtuYW1lOm5ld05hbWUsIC4uLm90aGVyc30gPSBoZXJvO1xuY29uc29sZS5sb2cob3RoZXJzKVxuLy97Y3JlYXRvcjogXCJNYXJ2ZWxcIiwgcG93ZXI6IFwiMTIwMFwifVxuY29uc3QgYWdlID0gMzRcbmNvbnN0IG5ld0hlcm8gPSAje1xuLi4ub3RoZXJzLCAvL3N5bnRheCBzcHJlYWRcbmFnZSwgLy9zaG9ydCBub3RhdGlvblxubmFtZTpcIkNhcCBBbWVyaWNhXCJcbn07XG5jb25zb2xlLmxvZyhuZXdIZXJvKVxuXG5jb25zdCBjb2xvcnMyID0gI1tcInllbGxvd1wiLCBcImJsdWVcIiwgXCJyZWRcIl07XG4vL2ZpbHRlciBtZXRob2RcbmNvbnN0IHJlZENvbG9yID0gY29sb3JzMi5maWx0ZXIoKGNvbG9yKT0+Y29sb3IgPT09IFwicmVkXCIpO1xuY29uc29sZS5sb2cocmVkQ29sb3IpXG4vLyNbXCJyZWRcIl1cblxuLy9FeGFtcGxlIDRcbmNvbnN0IHJlY29yZEV4YW1wbGUgPSBKU09OLnBhcnNlKCd7XCJ4XCI6XCJIZWxsb1wiLFwieVwiOltcIkJhbmFuYVwiLFwiQXBwbGVcIl19Jyk7XG5jb25zb2xlLmxvZyhyZWNvcmRFeGFtcGxlKTtcbi8vICN7eDogXCJIZWxsb1wiLCB5OiAjW1wiQmFuYW5hXCIsIFwiQXBwbGVcIl19XG5cbmNvbnN0IG9iakV4YW1wbGUgPSBKU09OLnN0cmluZ2lmeShyZWNvcmRFeGFtcGxlKTtcbmNvbnNvbGUubG9nKG9iakV4YW1wbGUpO1xuLy8gXCJ7eDogXCJIZWxsb1wiLCB5OiBbXCJCYW5hbmFcIiwgXCJBcHBsZVwiXX1cIlxuXG4vL0V4YW1wbGUgNVxuY29uc3QgZXJyb3JSZWNvcmRPYmogPSAje1xuICBvYmo6IHtcbiAgICBhOiBcImknbSBhbiBvYmplY3RcIlxuICB9LFxufTtcblxuLy9FcnJvciwgbm8gc2UgcHVlZGVuIHRlbmVyIGZ1bmNpb25lcy5cbmNvbnN0IGVycm9yUmVjb3JkRnVuY3Rpb24gPSAje1xuICBleGFtcGxlOiAoKSA9PiBhbGVydChcIkhlbGxvIFdvcmxkIVwiKVxufTtcblxuLy9OaW5n+m4gb3RybyBkYXRvIHF1ZSBubyBzZSB1biBwcmltaXRpdm8uXG5jb25zdCBlcnJvclJlY29yZERhdGUgPSAje1xuICBkYXRlOiBuZXcgRGF0ZSgpLFxufTtcblxuY29uc3QgZXJyb3JSZWNvcmRDbGFzcyA9ICN7XG4gIGNsYXNzOiBuZXcgQ2FyKCksXG59O1xuXG5jb25zdCBlcnJvclR1cGxlQ2xhc3MgPSAjW25ldyBDYXIoKV07XG5cbmNvbnN0IGVycm9yUmVjb3JkU3ltYm9sID0gI3sgW1N5bWJvbCgpXTogI3t9IH07ICIsInN5bnRheCI6Imhhc2giLCJkb21Nb2RlIjpmYWxzZX0=) creado por Rick Button y ver los ejemplos que realice. Muchas gracias por leer ;).

#### Referencias 
* https://exploringjs.com/deep-js/ch_shared-mutable-state.html

* https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Classes/Private_class_fields
* https://2ality.com/2020/05/records-tuples-first-look.html#restrictions-of-what-can-be-inside-records-and-tuples
* https://github.com/tc39/proposal-record-tuple
* https://rickbutton.github.io/record-tuple-playground/