1.2 Conceptos de typescript

Conceptos de TypeScript

Tal y como comente anteriormente, TypeScript es un SuperSet de ES6, ahora ES6 es un SuperSet de ES5... que quiere decir esto..

Tal y como vemos en la imagen, TypeScript, contiene todo lo que contiene ES6 y además agrega types y decorators.

Pero bueno vayamos un poco mas allá con TypeScript, osea vamos al código, bueno primero a la consola.

npm install -g  typescript

Aclaración: todos los ejemplos se encuentran en el github del libro.

Los ejemplos del código que vamos a ver en esta sección estan en la carpeta "entendiendo-angular-typescript"

ejemplo-01.ts

console.log("Hola TypeScript");

Ahora podemos ejecutar en consola nuestro ejemplo, simplemente poniendo:

node ejemplo-01.ts

Exactamente, node lo ejecuto directo y podemos ver que ahora imprimió nuestro "console.log", pero a nosotros nos importa que funcione en el navegador...

¿por lo tanto deberiamos tener un HTML que llame a nuestro TypeScript?

La respuesta es un rotundo NO, TypeScript necesita ser TRANSPILADO, osea que no es compilado, si no que el comando que instalamos por node, va a pasar de typescript a ES5, a menos que le indiquemos que pase a ES6 ( por ahora lo mejor que podemos hacer es pasar a ES5, ya que ES6 no esta soportado por todos los navegadores).

Para poder transpilar lo que vamos a hacer es:

tsc ejemplo-01.ts

Vamos a ver que la consola no devuelve nada, pero si vemos nuestro "navegador de carpetas" ( que raro que suena ), vamos a ver que se genero un JS , que se llama exactamente igual al TS que teníamos.

El código que genero es:

console.log("Hola TypeScript");

Si , bueno el "console.log" es igual para ambos, pero lo importante en este ejemplo súper básico es que vamos a poder utilizarlo en un html... vamos a crear algo básico:

index.html

<script src="ejemplo-01.js"></script>

Sin errores, venimos bien hasta ahora ;)

Vamos a ver algunas bondades de TypeScript

Veamos un ejemplo en JS y TS para ver cuales son los resultados, el ejemplo es simplemente llamar a una funcion que deberia recibir 2 numeros para sumarlos y luego mostrarlos por consola.

JS

function add (a,b){
    console.log( a + b );
}
add (1,3);
add (1, '3');

Resultado (ejecutado desde la consola de chrome directo):

Ahora veamos el mismo ejemplo pero en TS (este va a tener que transpilarse, por lo tanto lo vamos a agregar a ejemplo-02.ts):

function add(a:number, b:number){
    console.log( a + b);
}
add(1,3);
add(1,'3');

Al escribir este ejemplo en el VSC, me aparece lo siguiente:

Y cuando paro el cursor sobre el error:

Ya nos indica que un tipo "String" no puede asignarse a un tipo number.. claro un string no es un numerico... pero si JS me dejo hacerlo sin problemas, claro porque no tiene types...

Pero igual vamos a ejecutar el tsc para ver que pasa:

tsc ejemplo-02.ts

Claramente el VSC no se equivoco, no se puede asignar un string a un tipo number...

A pesar de esto, el transpilador nos creo el JS, debido a que este ERROR, es casi como un warning en realidad... debito a que JS permite hacer esto (pero deberiamos arregarlo igual)...

Vamos un poco a la explicación mas tecnica...

TypeScript al tener types nos deja asignar un tipo a una variable, como vemos en el ejemplo anterior, le dijimos a nuestras variables de la funcion, que son tel tipo number, por lo tanto, espera que lleguen dos numeros, no un numero y un string...

En TypeScript, se pone nombreDeVariable : tipo = asignacionDeValor

var miVariableNumerica:number = 10;

No es necesario que este inicializado con un valor.

Pero veamos los tipos que maneja typescript.

  • string

  • number

  • boolean

  • Array

  • Object

  • undefined

  • Enum

  • any

  • void

Mas alla de los tipos para las variables, podemos tipar la devolucion de las funciones... en el ejemplo de la imagen, vemos que esta tipado con void, osea que no devuevle nada... pero podriamos ponerle cualquiera de las enumeradas arriba y en el caso de no devolver el tipo que estamos esperando nos va a dar un error. Ademas si la funcion tiene una devolución, la variable que reciba esa devolución va a tener que ser del mismo tipo.

Features:

  • Types

  • Interfaces

  • Shapes

  • Decorators

Arrow function:

Arrow function, hace que no perdamos el scope de lugar.. por lo tanto el "this" nos va a funcionar en todos lados (no sabes que es "this", no te hagas problema, ya lo vamos a ver).

La estructura de un arrow function es:

() => {}

Las parentesis estan vacias a menos que reciba algun tipo de parametro, y luego lo que esta entre las llaves es lo que se ve a ejecutar en la funcion.

Multi-Line String:

var first_name: string= "Jorge";
var last_name: string = "Cano";
var twitter_user: string = "@jorgeucano";
var interpolation = `
    <div>
        <p>
            Hola soy <span> ${first_name} ${last_name} </span>
            Y mi twitter es ${twitter_user}
        </p>
    </div>
`

;

WOW really ??? yes :D !!!

El acento frances ` genera string multilineas... y ademas tenemos interpolation, podemos mezclar string con variables, con ${nombre_variable}

Podemos chequear el ejemplo, mira el archivo _ejemplo-03.ts , ejemplo-03.js y ejemplo-03.html, _el resultado de todo esto es:

Veamos que genero el el transpilador para poder hacer esto (ejemplo-03.js):

var first_name = "Jorge";
var last_name = "Cano";
var twitter_user = "@jorgeucano";
var interpolation = "\n    <div>\n        <p>\n            Hola soy <span> " + first_name + " " + last_name + " </span>\n            Y mi twitter es " + twitter_user + "\n        </p>\n    </div>\n";
document.getElementById('result').innerHTML = interpolation;

Claramente prefiero TS para esto jeje...

Clases

class Foo { foo:number; }
class Bar { bar: string; }

class Baz{
    constructor (foo:Foo, bar:Bar){}
}

let baz = new Baz(new Foo(), new Bar());

Veamos un poco el ejemplo:

Foo y Bar no tienen ningun tipo de incializador.. solo indican que tiene una variable cada una y su tipo.

Ahora Baz tiene un constructor (para los que nunca vieron un constructor, es una función que se ejecuta con la creación del objeto, por lo tanto cuando lo creamos tenemos que pasarle los parametros del contructor que se ejecuta, el constructor esta en todas las clases por defecto esta vacio, por lo tanto no es necesario escribirlo si va a estar vacio).

class Person{
    first_name:string;
    last_name:string;
    twitter_user?:string;
}

var persona = new Persona();
persona.first_name = "Jorge";
persona.last_name = "Cano";
persona.twitter_user = "@jorgeucano";

Las variables con el "?" antes del ":" para indicar el tipo, es que son opcionales.

En este caos, first_name y last_name son obligatorios para la clase, pero twitter_user es opcional.

Interfaces

Una interfaz es como un "contrato" para dentificar como es algo..

interface unaPersona{
    first_name:string;
    last_name:string;
    twitter_user?:string;
}

let a : unaPersona = {
    first_name = "Jorge",
    last_name = "Cano",
    twitter_user = "@jorgeucano"
}

Comparado la interfas unaPersona contra la clase Person, veremos que ya de por si la forma de Crearlos son distintos.

Uno es mas como una "especificación" de como tiene que ser y el otro es un objeto directo.

Shapes

Por debajo de TypeScript esta JavaScript, y por debajo de JavaScript esta normalmente un JIT (Just-In-Time compilador). Dada la semántica subyacente de JavaScript, los tipos suelen ser razonados por "formas". Estas formas subyacentes funcionan como interfaces de TypeScript y, de hecho, son como TypeScript compara tipos personalizados como clases e interfaces.

interface unaPersona{
    first_name:string;
    last_name:string;
    twitter_user?:string;
}

let a : unaPersona = {
    first_name = "Jorge",
    last_name = "Cano",
    twitter_user = "@jorgeucano"
}

class NotAnAction {
  type: string;
  constructor() {
    this.type = 'Constructor function (class)';
  }
}
class Person{
    first_name:string;
    last_name:string;
    twitter_user?:string;
    constructor(){
        this.first_name = "Jorge";
        this.last_name = "Cano";
        this.twitter_user = "@jorgeucano";
}

a = new Person(); // valid TypeScript!

A pesar de que unaPersona y Person tienen diferentes identificadores, tsc nos permite asignar una instancia de Person a una que tiene un tipo de unaPersona.

Esto se debe a que TypeScript sólo se preocupa de que los objetos tengan la misma forma. En otras palabras, si dos objetos tienen los mismos atributos, con las mismas tipologías, estos dos objetos se consideran del mismo tipo.

Diferencias entre VAR y LET

Varios ya me hicieron la pregunta de porque a veces uso VAR o LET en el código, por lo tanto queria dar a entender para que sirve cada uno...

Lo primero que vamos a hacer es ejecutar los siguiente en nuestra consola del navegador:

var a = 1; 
let b = 1;
while ( a < 10 ){
    var a = a + 1;
    let b = a;
}
console.log(a);
console.log(b);

Claramente algo esta pasando, si 'b = a;' y ' a = 10' porque 'b = 1'.

Aquí esta la diferencia, var es una variable "global" frente a let que es una variable de "scope", cuando utilizamos let, esta variable va a funcionar sobre el bloque en el que se encuentra, por lo tanto la variable "b" en el while NO es la misma que la variable "b" que esta por fuera, por eso mismo, "b" dentro del while en la ultima iteración vale 10, pero por fuera de la iteración vale 1.

PARA, no todo es tns archivo por archivo!

TypeScript, tiene un config para configurarlo a nuestro gusto:

{
    "compilerOptions":{
        "module":"commonjs",
        "target":"es5",
        "emitDecoratorMetadata":true,
        "experimentalDecorators":true,
        "noImplicitAny":false,
        "removeComments":false,
        "sourceMap":true
    },
    "exclude":{
        "node_modules",
        "dist/"
    }
}

Ya tenemos todos los conceptos basicos que tiene typescript para que podamos trabajar con Angular, si te quedo algo en el tintero, puedes hacerme una pregunta, o chequear en su web, todas las funcionalidades.

Last updated