Que es Typescript? Tipos, Clases e Interfaces
Tags: typescript, javascript, webdev, tutorial
Published: 2020-06-26 20:38:17

Typescript es un lenguaje "Tipado" en el que son requeridos los tipos de datos de las variables, los tipos de datos son estrictos y deben ser respetados.  Es un lenguaje creado por Microsoft, es open source (AYFK? si, Microsoft Open Source); Se puede implementar en FrontEnd o BackEnd.

Typescript brinda control sobre las aplicaciones antes de lanzarse a correr, también permite ver claramente para otro programador que es lo que quisiste escribir.  Este se puede implementar en Backend o FrontEnd: Angular, React, Node, entre otros.

#Desventajas
Todo tiene un costo, y en este caso Javascript te daba libertad para manejar los datos sin tener en cuenta el tipo de la variable; por lo que en Typescript hay que digitar obviamente mas codigo y tener en cuenta el tipo de datos (una cosa mas en la que pensar).

#VSCode
El IDE por excelencia según diferentes benchmarks, este funciona a la perfección con Typescript; todas las variables, objetos, clases traen su intellisense por defecto sin necesidad de extensiones; ahora si quieres algo mas alla, pues hay muchas extensiones que te pueden tunear el IDE, pero al igual que con la bebida (alcohol) procura no mezclar demasiadas extensiones.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/optx1yr9r87snmrr99hm.jpg)

Para definir una variable de un tipo simplemente debemos poner el nombre de la variable despues el signo de dos puntos (:) y el tipo de la variable.

```
const NombreVariable : string = 'A';
```

Nota: Procura usar siempre let en lugar de var.


```typescript
//En JScript podria reasignar a la variable X un valor numerico y a partir de ese momento
//la variable pasara a ser numeric; pero en Typescript esto mismo generaría un error.
const MyVar : string = 'Hello Sunshine!';
MyVar = 'Hola Solecito!';
MyVar = 1;  //! Error

//En Typescript si no se define el tipo, a partir de la primera definición toma el tipo
//de esta asignación, y no puede ser modificado el tipo de dicha variable.
const MyVarX = 'Hello Sunshine!';  //* Define como String a la variable MyVarX
MyVarX = 'Hola Solecito!';
MyVarX = 1; //!Error
```
#TYPES para Funciones
Podemos definir para las funciones tipos para cada uno de los argumentos, y para los valores de retorno.

```typescript
//En este caso al no definir un type, este tomara el type Any.
function sumatoria(numero1, numero2) {
  //Aquí en Javascript tengo que validar que estos argumentos en realidad son números
  //Que se pueden sumar, etc.  Solo hasta cuando se ejecute podríamos ver un error,
  //pero no es explicito.
  return numero1 + numero2;
}

//Puedo definir un value como any en Typescript de la siguiente manera
let variableDeCualquierTipo: any = 10;
//Esto no sirve de nada, por que en realidad seria como hacerlo en Javascript,
//pero haciendo o digitando mas codigo.

//Generando los tipos para la función de arriba seria
function sumatoriaTS(numero1: number, numero2: number): number {
  return numero1 + numero2;
}

//Al Llamar a esta función nos aseguramos un error si regresamos algo diferente de numero.
//o si alguno de los datos de entrada no es de tipo Number.
sumatoriaTS('1', 2); //Error, '1' es de tipo String.

//Error: Argument of type '"1"' is not assignable to parameter of type 'number'.ts(2345)

```
Al llamar a la función, VSCode nos dice sin necesidad de compilar inmediatamente un error gracias al Lint de Typescript:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/y2q8jamkfodncsycnlec.png)

Ya sé lo que algunos pensaran: Muy interesante, pero esto no es regresar a la edad de piedra, no es escribir de mas; La respuesta rápida seria: Si; pero aun la IA no ha avanzado tanto para que un IDE o lenguaje adivine que quieres hacer y evita que cometas errores, por ende este medio es lo mejor para validar que no cometas un error tipográfico o de lógica simple de tipos de dato.

#Tipos de Datos Custom
Los tipos de datos existentes en Typescript son:
- Boolean: Retorna true o false.
- String
- Array
- Tuple
- Enum
- Any: Visto en el ejemplo arriba.
- Void: No retorna nada.
- Null and Undefined
- Never: Retorna una excepción o un error.
- Object

Pero que pasa si quiero crear un nuevo tipo de datos; con Typescript esto es posible:
```typescript
type cedula = string;
let numeroCedula: cedula = '23039203293';
```
En este caso cree mi tipo Numero de Cedula en el que lo defini como de tipo string, de esa manera funcionaria como un alias, pero que pasaria si posteriormente cambio la asignacion a numero.

```typescript
type cedula = number;
let numeroCedula: cedula = '23039203293'; //Error, es number lo que se espera.
```

#Clases (OOP)
Una ventaja (por lo menos en mi caso) es la sintaxis similar a otros lenguajes para la creación de clases con argumentos privados, getter y setters.

```typescript
//
//Una de las ventajas de Javascript es poder usar Clases, Interfaces entre otros
class Person {
  //Esto no era posible en javascript.
  private name: string;
  private id: number;

  //Defino el constructor para esta clase.
  constructor(nombre: string, id: number) {
    //Asigno los argumentos del constructor a las variables privadas.
    this.name = nombre;
    this.id = id;
  }

  //Se crean los Getter and Setters para los campos que pueden ser accedidos mediante
  //estos métodos.
  getName() {
    return this.name;
  }

  setName(nombre: string) {
    this.name = nombre;
  }

  getId() {
    return this.id;
  }

  setId(id: number) {
    this.id = id;
  }
}

// Para definir un objeto de una clase, se realiza de manera similar a la definición de una variable
// de un tipo en particular, con la diferencia de la ejecución de su constructor.
const Edison: Person = new Person('Edison', 1);
```
En este caso creamos un objeto denominado Edison, el cual tiene un nombre inicial "Edison" y un Id 1.  Este objeto contiene todos los métodos públicos que han sido definidos en la clase.

Al igual que comúnmente en Programación Orientada a Objetos, estas clases en Typescript se pueden extender, como en el siguiente ejemplo:

```typescript
class Estudiante extends Person {
  private curso : string;

  constructor( name: string, id: number, curso: string){
    super(name, id);
    this.curso = curso;
  }

  //Error, esta clase esta haciendo sobre carga de la clase Person, pero esta es
  //de tipo number, pero en esta sobrecarga estoy regresando un String.
  getId() {  
    return `Estudiante ${super.getName()}, con id: ${super.getId}`
  }
}
```
Entonces vemos aquí que cometí un error, el cual para corregirlo debería regresar el mismo tipo de la original; el mismo VSCode me alerta de este error:

![Typescript Error overload](https://dev-to-uploads.s3.amazonaws.com/i/yqafich3gq48pfxcubu7.png)

```typescript
class Estudiante extends Person {
  private curso : string;

  constructor( name: string, id: number, curso: string){
    super(name, id);
    this.curso = curso;
  }

  getId() {
    return super.getId() * 100;
  }

  //Get and Set
  getCurso() {
    return this.curso;
  }

  setCurso(curso: string) {
    this.curso = curso;
  }
}
```
Poco a poco voy familizarizandome con TS, para instanciar esta nueva clase extendida lo haríamos de la siguiente manera:
```typescript
const NuevoEstudiante : Estudiante = new Estudiante( 'Ricardo', 2, '11-A');
```
Me gusta, no se si te has dado cuenta; pero puede parecer más complicado, aunque las ventajas de detección de errores justifican todo esto.

###Bonus
En VSCode para cambiar varias partes del código sin tener que cambiar uno a uno, puede presionar la tecla ALT y con clic del mouse seleccionar las diferentes partes que quiere editar al mismo tiempo.

#Interface
Una interface es un tipo abstracto, es como un contrato que permite determinar la estructura que debería tener un objeto.

Para el siguiente ejemplo crearemos una interface llamada Vehículo que tendrá un tipo custom denominado marca el cual es de tipo string, y algunos atributos propios de la interface Vehículo como lo son Marca, Modelo, Año, Color, y Tipo.  Con esta definición Typescript cuando defina un objeto de este "tipo" vehiculo, al no contar con alguno de los atributos de esta interface generará un error que puede ser corregido antes de correr la aplicación, esto gracias a la magia de Typescript.

```typescript
type Marca = string;

interface Vehiculo {
  marca: Marca;
  modelo: string;
  anio: number;
  color: string;
  tipo: string;
}

//!Error al definir me falto el campo color
const TC1V4 : Vehiculo = {
  marca: 'Hyundai',
  modelo: 'Tucson',
  anio: 2016,
  tipo: 'Jeep'
}
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/28al4u05x5xdk52bjkwd.png)

Algunas de las cosas que debemos tener en consideración son el tipo y el número de atributos; pero hay una flexibilidad la cual permite que si un atributo en una interface tiene el signo ?: se considera un atributo opcional, por lo que Typescript no generaría un error.

```typescript
interface Vehiculo {
  marca: Marca;
  modelo: string;
  anio: number;
  color?: string;
  tipo: string;
}
```
Para el ejemplo he puesto el atributo color con un interrogante, por lo que ahora Typescript considera este campo como "opcional" y no genera un error.
#Union Types
Con Typescript es posible definir un tipo que pueda ser de dos tipos; ejemplo un tipo FactorParametro puede ser de tipo string o number; es decir puedo enviar '1' o enviar 1 como argumento y al interior de la función operar esto.
```typescript
//Definimos dos tipos que pueden ser string o numero.
type FactorParametro = string | number;
type Resultado = string | number;

function Multiplicacion( numero1: FactorParametro, numero2: FactorParametro): Resultado{
  return numero1 * numero2; //Error, asi estaría devolviendo Any puesto que no esta definido el tipo en este return.
}
```
##Cast en Typescript
Para el ejemplo sera necesario "Castear" o forzar el tipo de dato de los argumentos para que puedan ser sumados como números, por lo que haremos el siguiente cambio:
```typescript
return Number(numero1) * Number(numero2);
```
Con esto ya no nos da error y lo que retorna seria un Number.

#Union Types con Interfaces
Esto que vimos con diferentes tipos de datos para un tipo de dato custom tambien lo podemos efectuar con diferentes interfaces, veamos un ejemplo con dos interfaces donde creamos un objeto abstracto con uno de ellos.
```typescript
//Definimos dos interfaces, y creamos un tipo que puede ser una o la otra.
interface InterfaceUno {
  Propiedad1: string;
}

interface InterfaceDos {
  Propiedad2: number;
}

type CualquieraDeLasDos = InterfaceUno | InterfaceDos;

const LaInterface : CualquieraDeLasDos = {
  Propiedad1: 'HEYY'
}
```
Ante esto no tengo ningún problema, y Typescript valida que cree el objeto con la InterfazUno.  La creación de un objeto con la InterfazDos seria de la siguiente manera:
```typescript
const LaInterface : CualquieraDeLasDos = {
  Propiedad2: 3
}
```
No puedo crear con la Propiedad2 un string debido a que la interface lo ha identificado como number en su creación.

## Intersection Types
Es un concepto similar al anterior pero en este caso no es "uno o el otro", sino que deben ser los dos.  En caso contrario obtendremos un error, siguiendo el mismo caso anterior, lo unico que debemos cambiar seria:
```typescript
type DebenSerLasDos = InterfaceUno & InterfaceDos;
```
Cambiamos el simbolo | (pipe or) por el simbolo & (ampersan, and); al hacer esto debo incluir todas las propiedades de las dos interfaces:
```typescript
const InterObjeto : DebenSerLasDos = {
  Propiedad2: 3,
  Propiedad1: 'A'
}

const ErrorIntersInterface : DebenSerLasDos = {
  Propiedad1: 'A'
}
//!Type '{ Propiedad1: string; }' is not assignable to type 'DebenSerLasDos'.
//!Property 'Propiedad2' is missing in type '{ Propiedad1: string; }' but required in type 'InterfaceDos'.ts(2322)
```
Tambien, si se tiene el mismo nombre de propiedad entre dos interfaces; con solo definirla una vez ya no obtenemos un error:
```typescript
//Definimos dos interfaces, y creamos un tipo que puede ser una o la otra.
interface InterfaceInt1 {
  Propiedad1: string;
}

interface InterfaceInt2 {
  Propiedad1: string;
}

type DebenSerLasDos = InterfaceInt1 & InterfaceInt2;

const InterObjeto : DebenSerLasDos = {
  Propiedad1: '3',
}
```

En un siguiente Post continuaré explorando sobre Typescript, si gusta puede ver el código fuente en mi repositorio de GitHub:

[Ver Repositorio GitHub >>>](https://github.com/Edisonsan/typescript)

***
AQUI LA CONTINUACION...
[CONTINUAMOS EN EL SIGUIENTE POST =>](https://dev.to/edisonsanchez/typescript-shapes-44dc)