Javascript

V1

V2

V3

V4

V5

V6

V7

V5.1

Saber más sobre versiones: https://semver.org/lang/es/

Versiones de JavaScript

ES6 code

Babel

ES5

Transpila

Seguridad de que lo soporte su navegador

Métodos Array Helper

forEach

filter

map

find

every

reduce

some

forEach

forEach

red

green

blue

función de iteración

var colors = ['red', 'green', 'blue'];

for(var i = 0; i < colors.length; i++) {
    console.log(colors[i]);
}

colors.forEach(function(color) {
    console.log(color);
});

colors.forEach(color=> {
    console.log(color);
});

array 'colors'

forEach (II)

// Crear un arreglo de números
var numbers = [1, 2, 3, 4, 5];

// Crear una variable para controlar la suma
var sum = 0;

// A través de un ciclo, incrementar la variable sum según arreglo numbers
function adder(number){
    sum += number;
}
numbers.forEach(adder);

// Imprimir la variable sum
console.log(sum);

Por qué usar forEach

map

var numbers = [1, 2, 3];
var doubledNumbers = [];

for(var i = 0; i < numbers.length; i++) {
    doubledNumbers.push(numbers[i] * 2);
}

var doubled = numbers.map(function(number){
    return number * 2;
});

console.log(doubled);
console.log(doubledNumbers);

¿Cómo funciona el map?

map

1

2

3

Arreglo "Numbers"

función de iteración

función de iteración

función de iteración

retorna

retorna

retorna

2

4

6

Arreglo resultante

map (II)

var cars = [
    { model: 'Buik', price: 'CHEAP' },
    { model: 'Camaro', price: 'expensive' }
];

var prices = cars.map(function(car){
    return car.price;
});

console.log(prices);

Uso de map

filter

fruta

vegetal

fruta

Arreglo "products"

función de iteración

retorna

fruta

fruta

Arreglo resultante

función de iteración

función de iteración

retorna

retorna

true

false

true

filter

var products = [
    { name: 'banano', type: 'fruta' },
    { name: 'papa', type: 'vegetal' },
    { name: 'chayote', type: 'vegetal' },
    { name: 'naranja', type: 'fruta' },
];

filteredProducts = [];

for (var i = 0; i < products.length; i++) {
    if (products[i].type == 'fruta') {
        filteredProducts.push(products[i]);
    }
}

console.log(filteredProducts);

filtered = products.filter(function(product) {
    // if(product.type === 'fruta') {
    //     return true;
    // }
    return product.type === 'fruta';
})

console.log(filtered);

filter (II)

var products = [
    { name: 'banano', type: 'fruta', quantity: 0, price: 1 },
    { name: 'papa', type: 'vegetal', quantity: 10, price: 15 },
    { name: 'chayote', type: 'vegetal', quantity: 30, price: 9 },
    { name: 'naranja', type: 'fruta', quantity: 3, price: 5 },
];

// Type vegetal, quantity mayor que 0 y price mayor que 10
var filtered = products.filter(function(product) {
    return product.type === 'vegetal' 
           && product.quantity > 0 
           && product.price > 10;
});

console.log(filtered);

¿Por qué filter?

var post = { id: 3, title: 'Nuevo post' };
var comments = [
    { postId: 3, content: 'Buen post' },
    { postId: 6, content: 'Está bueno' },
    { postId: 3, content: 'Estupendo' }
];

function commentsForPost(post, comments) {
    return comments.filter(function(comment) {
        return comment.postId === post.id;
    });
}

console.log(commentsForPost(post, comments));

Post

Post

Comment

Comment

Comment

id = 3

id = 6

find

find

var users = [
    { name: 'Luis' },
    { name: 'Carlos' },
    { name: 'Pedro', id: 4 },
    { name: 'Pedro' }
];

var user;

for(var i = 0; i < users.length; i++) {
    if(users[i].name === 'Pedro') {
        user = users[i];
        break;
    }
}

console.log(user);

var found = users.find(function(user) {
    return user.name === 'Pedro'
});

console.log(found);

Uso de find

var posts = [
    { id: 1, title: 'Nuevo post' },
    { id: 2, title: 'Post anterior' }
];

var comment = { postId: 1, content: 'Gran post' };

function postForComment(comment, posts) {
    return posts.find(function(post) {
        return post.id === comment.postId;
    });
}
var post = postForComment(comment, posts);

console.log(post);

Uso de find

every y some

&&

&&

= false

Every

every y some

II

II

= true

Some

every y some

var computers = [
    { name: 'Apple', ram: 24 },
    { name: 'Compaq', ram: 4 },
    { name: 'Acer', ram: 32 }
];

var allComputersCanRunProgram = true;
var onlySomeComputersCanRunProgram = false;

for(var i = 0; i < computers.length; i++) {
    var computer = computers[i];

    if(computer.ram < 16) {
        allComputersCanRunProgram = false;
    } else {
        onlySomeComputersCanRunProgram = true;
    }
}

console.log(allComputersCanRunProgram);
console.log(onlySomeComputersCanRunProgram);
var computers = [
    { name: 'Appled', ram: 24 },
    { name: 'Compaq', ram: 4 },
    { name: 'Acer', ram: 32 }
];

var allComputersCanRunProgram = true;
var onlySomeComputersCanRunProgram = false;


allComputersCanRunProgram = computers.every(function(computer) {
    return computer.ram > 16;
});

onlySomeComputersCanRunProgram = computers.some(function(computer) {
    return computer.ram > 16;
});

console.log(allComputersCanRunProgram);
console.log(onlySomeComputersCanRunProgram);

Clásico

Con helper

every y some - Usos

function Field(value) {
    this.value = value;
}

Field.prototype.validate = function() {
    return this.value.length > 0;
}

var username = new Field('2cool');
var password = new Field('my_password');
var birthdate = new Field('10/10/2010');

var fields = [username, password, birthdate];

var formIsValid = fields.every(function(field) {
    return field.validate();
});

console.log(formIsValid);

if(formIsValid) {
    // Permitir enviar formulario
} else {
    // Mostrar mensajes de validación
}

reduce

reduce

var numbers = [ 10, 20, 30 ];
var sum = 0;

for(var i = 0; i < numbers.length; i++) {
    sum += numbers[i];
}

console.log(sum);

sum = numbers.reduce(function(sum, number){
    return sum + number;
}, 0);

console.log(sum);

reduce (II)

var primaryColors = [
    { color: 'red' },
    { color: 'yellow' },
    { color: 'blue' }
];

var colors = primaryColors.reduce(function(previous, primaryColor) {
    previous.push(primaryColor.color);
    return previous;
}, []);

console.log(colors);

reduce - Usos

function balancedParens(string) {
    return !string.split("").reduce(function(previous, char) {
        if(previous < 0){ return previous; }
        if(char === '(') { ++previous; } 
        if (char === ')') { --previous; }

        return previous;
    }, 0);
}

console.log(balancedParens('()'));

const y let

function count(targetString) {
    var characters = ['a', 'e', 'i', 'o', 'u'];
    var number = 0

    for(var i = 0; i < targetString.length; i++) {
        if(characters.includes(targetString[i])) {
            number++;
        }
    }

    return number;
}

console.log(count('aeiobzxceiaibiox'));
function count(targetString) {
    const characters = ['a', 'e', 'i', 'o', 'u'];
    let number = 0

    for(var i = 0; i < targetString.length; i++) {
        if(characters.includes(targetString[i])) {
            number++;
        }
    }

    return number;
}

console.log(count('aeiobzxceiaibiox'));

template string

function getMessage() {
    const year = new Date().getFullYear();
    return "El año actual es: " + year;
}

console.log(getMessage());

ES5

function getMessage() {
    const year = new Date().getFullYear();
    return `El año actual es: ${year}`;
}

console.log(getMessage());

ES6

Arrow functions

// const add = function(a, b) {
//     const sum = a + b;
//     return sum;
// }

// const add = (a, b) => {
//     const sum = a + b;
//     return sum;
// }

const add = (a, b) =>  a + b;

console.log(add(2, 3));

Arrow functions (II)

// const double = number => 2 * number;

// const double = (number => 2 * number);

// console.log(double(3));

const numbers = [1, 2, 3];

const double = numbers.map(number => 2 * number);

console.log(double);

Arrow functions (III)

const team = {
    members: ['Luis', 'Carlos'],
    teamName: 'Super Power',
    // teamSummary: function(){
    //     return this.members.map(function(member){
    //         return `El miembro ${member} pertenence al team: ${this.teamName}`;
    //     }.bind(this));
    // }
    teamSummary: function(){
        var self = this;
        return this.members.map(member => `El miembro ${member} pertenence al team: ${self.teamName}`);
    }
}

console.log(team.teamSummary());

Arrow functions (III)

Literal Object (I)

function createBookShop(inventory) {
    return {
        inventory,
        inventoryValue() {
            return this.inventory.reduce((total, book) => total + book.price, 0)
        },
        priceForTitle(title) {
            return this.inventory.find(book => book.title === title).price;
        }
    }
}

const inventory = [
    { title: 'Harry Potter', price: 10 },
    { title: 'Eloquent JavaScript', price: 15}
];

const bookShop = createBookShop(inventory);

console.log(bookShop.inventoryValue());
console.log(bookShop.priceForTitle('Harry Potter'));

Funciones con argumentos predeterminados

function makeAjaxRequest(url, method = 'GET') {
    return method;
}

console.log(makeAjaxRequest('google.com', null));
console.log(makeAjaxRequest('google.copm', 'POST'));

Funciones con argumentos predeterminados (II)

function User(id) {
    this.id = id;
}

function generateId() {
    return Math.random() * 99999;
}

function createAdminUser(user = new User(generateId())) {
    user.admin = true;
    return user;
}

const user = new User(generateId());
const admin = createAdminUser();

console.log(user);
console.log(admin);

Operador rest

function addNumbers(...numbers) {
    return numbers.reduce((sum, number) => {
        return sum + number;
    }, 0);
}

console.log(addNumbers(1, 2, 3, 4, 5));

Operador spread

const defaultColors = ['red', 'green'];
const userFavoriteColors = ['orange', 'yellow'];

console.log(defaultColors.concat(userFavoriteColors));
console.log(['blue', ...defaultColors, ...userFavoriteColors]);
console.log([...defaultColors, userFavoriteColors]);

function validateShoppingList(...items) {
    if(items.indexOf('Cereales') < 0) {
        return [ 'Cereales', ...items ];
    }

    return items;
}

console.log(validateShoppingList('naranjas', 'pan', 'huevos'));

Operadores rest y spread

const MathLibrary = {
    calculateProduct( ...rest ) {
        console.log('calculateProduct está en desuso. Por favor use el método multiply');
        return this.multiply( ...rest );
    },
    multiply(a, b) {
        return a * b;
    }
}

console.log(MathLibrary.calculateProduct(3, 2));

Desestructuración 

var expense = {
    type: "Negocios",
    amount: "C$45"
}

// var type = expense.type;
// var amount = expense.amount;

// ES6

const { type, amount } = expense;
// Ambas instrucciones en una
// const { type } = expense;
// const { amount } = expense;

console.log(type);
console.log(amount);

Desestructuración (II) 

var savedFile = {
    extension: 'jpg',
    name: 'foto',
    size: 15050
}

function fileSummary({name, extension, size}, {color}) {
    return `${color}, El archivo ${name}.${extension} tiene un tamaño de: ${size}`;
}

console.log(fileSummary(savedFile, {color: 'rojo'}));

Desestructuración (III) 

const companies = [
    'Google',
    'Facebok',
    'Microsoft'
];

// const [ name1, name2, name3] = companies;
// console.log(name1);

// const { length } = companies;
// console.log(length);

const [ name, ...rest ] = companies;
console.log(rest);

Desestructuración (IV) 

// const companies = [
//     {name: 'Google',loc: 'Mountain View'},
//     {name: 'Facebook', loc: 'Menlo Park'},
//     {name: 'Uber', loc: 'San Francisco'}
//   ];

// const [{loc}] = companies;
// console.log(loc);

const Google = {
    locations: ['New York', "Mountain View", 'London']
}

const { locations: [...loc] } = Google;
console.log(loc);

Cuándo usar Desestructuración

function signup( {username, password, email, dateOfBirth, city} ) {
  // Con edestructuración no importa el orden de los parámetros
  // crear un nuevo usuario
}
// líneas de código
// líneas de código
// líneas de código
// líneas de código
// líneas de código
// líneas de código

const user = {
  username: 'minombre',
  password: 'micontraseña',
  email: 'miemail@example.com',
  dateOfBirth: '1/1/1984',
  city: 'Rivas'
}

signup(user);

Cuándo usar Desestructuración (II)

const points = [
  [4, 5],
  [10, 2],
  [0, 6]
];

const graph = points.map(function([x, y]) {
  return { x, y}
});

console.log(graph);

Introducción a clases

function Car(options) {
  this.title = options.title;
}

Car.prototype.drive = function(){
  return 'vroom';
}

const car = new Car({ title: 'Focus' });
console.log(car.drive());
console.log(car);

Herencia con prototipos

function Car(options) {
  this.title = options.title;
}

Car.prototype.drive = function(){
  return 'vroom';
}

function Toyota(options) {
  Car.call(this, options);
  this.color = options.color;
}

Toyota.prototype = Object.create(Car.prototype);
Toyota.prototype.constructor = Toyota;

Toyota.prototype.honk = function() {
  return 'Beep';
}

const toyota = new Toyota({ color: 'red', title: 'Diario' });

console.log(toyota);
console.log(toyota.drive());
console.log(toyota.honk());

Refactoring

class Car {
  constructor({ title }){
    this.title = title;
  }
  drive() {
    return 'vroom'
  }
}

const car = new Car({ title: 'Toyota'});
console.log(car);
console.log(car.drive());

Herencia

class Car {
  constructor({ title }){
    this.title = title;
  }
  drive() {
    return 'vroom'
  }
}

class Toyota extends Car {
  constructor(options) {
    super(options);
    this.color = options.color;
  }
  honk() {
    return 'Beep';
  }
}

const toyota = new Toyota({ color: 'red', title: 'Conducción diaria' });
console.log(toyota.honk());
console.log(toyota.drive());
console.log(toyota);

Generadores (Generators)

Antes de continuar con generators - for...of

const colors = ['red', 'green', 'blue'];

for(let color of colors) {
  console.log(color);
}

const numbers = [1, 2, 3, 4];

let sum = 0;

for(let number of numbers) {
  sum += number;
}

console.log(sum);

Generators

En la tienda

En la acera

Generators

function* shopping() {
  // Caminando por la acera

  // Entrando en la tienda con dinero

  const stuffFromTheStore = yield 'cash';

  // De regreso a la casa
  return stuffFromTheStore;
}

// Cosas en la tienda
const gen = shopping();
console.log(gen.next()); //Saliendo de la casa
// Entró a la tienda
// Caminando por el pasillo de la tienda
// Compramos las cosas

console.log(gen.next('compras')); //Saliendo de la tienda con las compras

Generators: un paso más

function* shopping() {
  // Caminando por la acera

  // Entrando en la tienda con dinero

  const stuffFromTheStore = yield 'cash';

  // Ir a la sección de ropa limpia
  const cleanClothes = yield 'ropa limpia';

  // De regreso a la casa
  return [stuffFromTheStore, cleanClothes];
}

// Cosas en la tienda
const gen = shopping();
console.log(gen.next()); //Saliendo de la casa
// Entró a la tienda
// Caminando por el pasillo de la tienda
// Compramos las cosas

console.log(gen.next('compras')); //Saliendo de la tienda con las compras
console.log(gen.next('Rompa limpia'));

for...of y Generators

function* colors() {
  yield 'red';
  yield 'green';
  yield 'blue';
}

const gen = colors();
// console.log(gen.next());
// console.log(gen.next());
// console.log(gen.next());

const myColors = [];
for (const color of colors()) {
  myColors.push(color);
}

console.log(myColors);

Ejemplo práctico

const engineeringTeam= {
  size: 3,
  department: 'Engineering',
  lead: 'Juan',
  manager: 'Carlos',
  engineer: 'Jorge'
}

function* teamIterator(engineeringTeam) {
  yield engineeringTeam.lead;
  yield engineeringTeam.manager;
  yield engineeringTeam.engineer;
}

let names = [];
for(const name of teamIterator(engineeringTeam)) {
  names.push(name);
}

console.log(names);

Delegar Generators

const testingTeam = {
  lead: 'Amanda',
  tester: 'Oscar'
}

const engineeringTeam = {
  testingTeam,
  size: 3,
  department: 'Engineering',
  lead: 'Juan',
  manager: 'Carlos',
  engineer: 'Jorge',
}

function* TeamIterator(team) {
  yield team.lead;
  yield team.manager;
  yield team.engineer;
  const testingTeamGenerator = TestingTeamIterator(team.testingTeam);
  yield* testingTeamGenerator;
}

function* TestingTeamIterator(team) {
  yield team.lead;
  yield team.tester;
}

let names = [];
for(const name of TeamIterator(engineeringTeam)) {
  names.push(name);
}

console.log(names);

Symbol.iterator con Generators

const testingTeam = {
  lead: 'Amanda',
  tester: 'Oscar',
  [Symbol.iterator]: function* () {
    yield this.lead,
    yield this.tester
  }
}

const engineeringTeam = {
  testingTeam,
  size: 3,
  department: 'Engineering',
  lead: 'Juan',
  manager: 'Carlos',
  engineer: 'Jorge',
}

function* TeamIterator(team) {
  yield team.lead;
  yield team.manager;
  yield team.engineer;
  yield* team.testingTeam;
}

let names = [];
for(const name of TeamIterator(engineeringTeam)) {
  names.push(name);
}

console.log(names);

Generators con recursividad

Generators con recursividad

class Comment {
  constructor(content, children) {
    this.content = content;
    this.children = children;
  }

  *[Symbol.iterator] () {
    yield this.content;
    for (const child of this.children) {
      yield* child;
    }  
  }
}

const children = [
  new Comment('Buen comentario', []),
  new Comment('Mal comentario', []),
  new Comment('ahhh', [])
];

const tree = new Comment('Gran post', children);
// console.log(tree);

const values = [];
for (const value of tree) {
  values.push(value);
}

console.log(values);

Ejemplos de uso: reddit.com, sección de comentarios

Promises (promesas)

Promises (promesas)

Problema

Promises (promesas)

Solución

3 estados de las promesas

Terminología de las promesas

Crear promesas

Desde la consola del navegador, pegar y probar

promise = new Promise((resolve, reject) => {
  resolve();
});
promise = new Promise((resolve, reject) => {
  reject();
});

reject y catch

promise = new Promise((resolve, reject) => {
  resolve();
});

promise
  .then(() => {
    console.log("Finalmente terminó");
  })
  .then(() => {
    console.log("También fuí ejecutado");
  })
  .catch(() => {
    console.log('Uh oh');
  });

Ejemplo práctico

Timer

Timer

¿Qué es lo que el programa hace?

  1. Mostrar un timer
  2. Mostrar un borde animado alrededor del timer

Implementación

Debe haber un evento a la espera de un click en el botón "Inicio"

Dibujar un borde alrededor del timer

Comenzar la cuenta regresiva

Cada vez que reduce el conteo, se actualiza el borde

Cada vez que reduce el conteo, se actualiza el texto

Si el conteo y el timer llega a cero

Resetear el borde

Resetear el timer para que esté listo para otra corrida

Emitir evento de inicio del timer

Emitir evento 

Emitir evento indicando que timer llegó a 0

Implementación

class Timer

start()

pause()

onDurationChange()

tick()

costructor(durationInput, startButton, pauseButton)

El valor de 'this'

¿Hizo la definición de la función como arrow function?

Si escribe console.log(this) en la primera línea válida de la arrow function, el valor de this será el contenedor del console log.

¿Hay una llamada a "bind", "call" o "apply" cuando se invoca la función?

this es igual al primer argumento de "bind", "call" o "apply".

En todos los otros casos

this es igual a lo que esté a la izquierda del "." del método de llamada

Javascript

Importante

"No piense que la programación no es para usted."

 

Eso no está permitido :)

 

Todos tenemos ritmos diferentes. Es cuestión de codificar y codificar hasta dominar el lenguaje.

Configurar el entorno

Instalar del editor Visual Studio Code: https://code.visualstudio.com/

Fundamentos de Javascript

Hola Mundo

alert('Hola Mundo');

Introducción a JS

Javascript en una lenguaje de programación de alto nivel,

orientado a objetos y multiparadigma.

Instrucción para que la computadora haga cosas

No nos preocupamos de cosas complejas como manejo de memoria

Basado en objetos para almacenar la mayor de los tipos de datos

Diferentes estilos de programación

Rol de JS en el DW

Rol de JS en el DW

Efectos dinámicos y aplicaciones Web en el navegador

Aplicaciones Web en el servidor

Aplicaciones móviles nativa

Aplicaciones de escritorio nativa

Rol de JS en el DW

ES5

ES6/ ES2015

ES7/ ES2016

ES8/ ES2017

ES9/ ES2018

ES10/ ES2019

ES11/ ES2020

Enlazar archivo Javascript

<script src="script.js"></script>

Variables

let js = 'amazing';

console.log(10 + 15 + 30);

// Las variable pueden contener letra, números, guión bajo y signo de dólar
// Tampoco es conveniente usar palabras reservadas
// Usa nombres de variables descriptivos

let firstName = 'Wilfredo Meneses';

console.log(firstName);
console.log(firstName);
console.log(firstName);

let myFirtsJob = 'Programador';
let myCurrentJob = 'Profesor';
console.log(myFirtsJob);

Tipo

Valor

OBJETO

PRIMITIVO

let me = {
  name: "Wilfredo"
};
let firstName = 'Wilfredo Meneses';
let myFirtsJob = 'Programador';
let myCurrentJob = 'Profesor';

7 tipos primitivos

let age = 23;
  1. Number: número de punto flotante (para enteros y decimales)
  2. String: secuencia de caracteres (usado para texto)
  3. Boolean: tipo lógico que solo puede ser true o false
  4. Undefined: valor tomado por una variable que todavía no ha sido definida ('empty value
  5. Null: también significa 'empty value'
  6. Symbol (ES2015: valor que es único y no puede ser cambiado (no útil pot ahora)
  7. BigInt (ES2020):  Entero grande que no puede contener el Number
let firstName = 'Luis';
let completed = false;
let children;

Tipo dinámico

No tenemos que definir manualmente el tipo de dato del valor que almacena una variable. En su lugar el tipo de dato es determinado de forma automática.

Tipos de datos

let javascriptIsFun = true;
console.log(javascriptIsFun);

console.log(typeof true);
console.log(typeof javascriptIsFun);
console.log(typeof 23);
console.log(typeof 'Wilfredo');

javascriptIsFun = 'Sí!';
console.log(typeof javascriptIsFun);

let year;
console.log(year);
console.log(typeof year);

year = 2020;
console.log(typeof year);

Let, const y var

let y const incluido en ES6

let age = 37;
age = 35;

const birthYear = 1991;

var job = 'Programador';
job = 'Profesor';

Operadores básico

// Operadores matemáticos
const now = 2020;
const ageWilfredo = now - 1983;
const ageLuisa = now - 1984;

console.log(ageWilfredo, ageLuisa);

console.log(ageWilfredo * 2, ageWilfredo / 2, 2 ** 3);

const firstName = 'Wilfredo';
const lastName = 'Meneses';

console.log(firstName + ' ' + lastName);

// Operador de asignación
let x = 10 + 5;
x += x + 5;
x *= 4;
x++;
x--;
x--;
console.log(x);

// Operadores de comparación
console.log(ageWilfredo > ageLuisa);
console.log(ageLuisa >= 36);

const luisaIsUnderAge = ageLuisa < 18;
console.log(luisaIsUnderAge);

Precedencia

// Ver la siguinete ruta: 
// https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Operadores/Operator_Precedence

const now = 2020;
const ageWilfredo = now - 1983;
const ageLuisa = now - 1984;

console.log(now - 1991 > now - 2018);

console.log(25 - 10 - 5);

let x, y;
x = y = 25 - 10 - 5;

console.log(x, y);

const averageAge = (ageWilfredo + ageLuisa) / 2;

console.log(averageAge);

Typescript

¿Qué es Typescript?

El Sistema tipado de  Typescript?

  • Ayuda a detectar errores durante el desarrollo.
  • usa "Types annotations" para analizar nuestro código
  • Sólo está activo durante el desarrollo
  • No provee optimización de rendimiento

El Sistema tipado de  Typescript?

Código Typescript

(Javascript con Types Annotations)

Compilador Typescript

Javascript plano

El navegador ejecuta Javascript plano, este no sabe que utilizamos Typescript

Probemos...

En resumen

Escribir Typescript es lo mismo que escribir Javascript con documentación extra.

 

Typescript no tiene efecto en cómo su código es ejecutado en el navegador.

 

La mejor manera de pensar en Typescript es como un amigo que está sentado atrás mientras estamos codificando

Configurar entorno

npm install -g typescript ts-node
tsc --help

Configurar editor

  • Agregar la ruta "code"
  • Instalar la extensión Prettier - Code formatter
  • Aplicar prettier al guardar (Prettier on save)
  • Usar comilla simples con Prettier
  • Usar dos espacios para indentación
  • Tema "Solarised Light"

La primera App

fetchjson

// Desde la terminal

mkdir fetchjson
cd fetchjson
npm init -y
npm install axios
touch index.ts
code .
// En index.ts

import axios from 'axios';

const url = 'http://jsonplaceholder.typicode.com/todos/1';

axios.get(url).then(response => {
  console.log(response.data);
});
// Desde la terminal

tsc index.ts
node index.js

// También se puede usar el paquete
ts-node index.ts

Hagamos cambios

Insertemos algunos errores en el código

import axios from 'axios';

const url = 'http://jsonplaceholder.typicode.com/todos/1';

axios.get(url).then(response => {
  const todo = response.data;

  const ID = todo.ID;
  const title = todo.Title;
  const finished = todo.finished;

  console.log(`
    Tarea con el ID: ${ID}
    Tiene el título: ${title}
    ¿Está finalizada?: ${finished}
  `);
});

Capturar errores con Typecript

Uso de Interface

import axios from 'axios';

const url = 'http://jsonplaceholder.typicode.com/todos/1';

interface Todo {
  id: number,
  title: string,
  completed: boolean
}

axios.get(url).then(response => {

  const todo = response.data as Todo;

  const id = todo.id;
  const title = todo.title;
  const completed = todo.completed;

  console.log(`
    Tarea con el ID: ${id}
    Tiene el título: ${title}
    ¿Está finalizada?: ${completed}
  `);
});

Capturar más errores

import axios from 'axios';

const url = 'http://jsonplaceholder.typicode.com/todos/1';

interface Todo {
  id: number,
  title: string,
  completed: boolean
}

axios.get(url).then(response => {

  const todo = response.data as Todo;

  const id = todo.id;
  const title = todo.title;
  const completed = todo.completed;

  // Si invertimos el order obtendremos un error
  logTodo(id, title , completed);
});

const logTodo = (id:number, title:string, completed:boolean) => {
  console.log(`
    Tarea con el ID: ${id}
    Tiene el título: ${title}
    ¿Está finalizada?: ${completed}
  `);
}

Objetivos del curso

Entender los tipos en TS

Fuciones de tipado + anotaciones

Archivos de definición de tipos

Arreglos en TS

Sistema de módulos

Classes + Refresher en TS

Proyectos

Sintaxis + características

Patrones de diseño

Tipos

Un tipo es una manera fácil de de hacer referencia a diferentes propiedades y funciones que tiene un valor

Tipos

"rojo"

Es un string

Es un valor que tiene todas las propiedades y métodos que asumimos tiene un string 

Tipos

Propiedades y métodos que tiene un String

chartAt()

charCodeAt()

concat()

includes()

endsWit()

indexOf()

lastIndexOf()

localeCompare()

match()

Tipos

Tipo

Valores que tiene el tipo

string

 

number

 

boolean

 

date

 

Todo

'hola'              ""          'Hoy es lunes'

 

.00034          -20          400000

 

true               false

 

new Date()

 

{id: 1, completed: true, title:"Botar la basura"

Tipos

Tipos

Tipos Primitivos

Tipos Objetos

number, boolean, void, undefined, string, symbol, null

funciones, arreglos, clases, objetos

Tipos

¿Por qué debemos tener cuidado con los tipos?

Los tipos son utilizados por el compilador de Typescript para analizar errores en nuestro código

Los tipos son utilizados por otros desarrolladores para entender qué valores están fluyendo en el código

Ejemplo

// Observer que solo se acceder a propiedades
// y métodos del tipo

const today = new Date();

today.getMonth();

const person = {
  age: 20,
}

class Color {

}

const red = new Color();

¿Dónde usar tipos?

En todo!

Anotaciones e inferencias

Tipo de anotación + inferencia de tipo

Variables

Funciones

Objetos

Definición simple + vista general

 

Ejemplos

 

¿Por qué debemos tener cuidado?

 

¿Cuándo usarlos?

Tipo anotaciones

Tipo inferencia

Código que agregamos para indicarle a Typescript a cuál tipo de valor hará referencia una variable.

Typescript trata de descifrar a cuál tipo de valor hará referencia una variable.

Nosotros le indicamos a Typescript el tipo

Tipo Anotaciones

Tipo Inferencia

Typescript adivina el tipo

Object Literal Annotations

// ..

// Array
let colors: string[] = ['red', 'green', 'blue'];
let myNumbers: number[] = [1, 2, 3, 4];
let truths: boolean[] = [true, true, false];

// Clases
class Car {

}

let car: Car = new Car();

// Objet literal
let point: {x: number; y:number} = {
  x: 10,
  y: 20
};

annotations/variables.ts

Anotaciones en funciones

// ..

// Array
let colors: string[] = ['red', 'green', 'blue'];
let myNumbers: number[] = [1, 2, 3, 4];
let truths: boolean[] = [true, true, false];

// Clases
class Car {

}

let car: Car = new Car();

// Objet literal
let point: {x: number; y:number} = {
  x: 10,
  y: 20
};

annotations/variables.ts

Entender Inferencias

Tipos de Inferencias

const color = 'red';

Declaración de variable

Inicialización de variable

Si la declaración y la inicialización están en la misma línea, Typescript indagará por nosotros el tipo de la variable 'color'

¿Entonces cuándo usar anotaciones?

Como desarrolladores le decimos a Typescript el tipo

Tipo anotaciones

Tipo inferencia

Typescript adivina el tipo

Siempre

¿Cúando usarlo?

¿Cúando usarlo?

Cuando declaramos una variable en una línea y luego la inicializamos

Cuando declaramos una variable en una línea y la inicializamos más tarde

Cuando una función retorna el tipo 'any' y requerimos aclarar el tipo 

Tipo 'any'

JSON.parse()

'false'

'4'

'{"value": 5}'

'{"name": "Wilfredo"}'

JSON.parse()

JSON.parse()

JSON.parse()

boolean

number

{value: number}

{name: string}

Ideal

JSON.parse()

'false'

'4'

'{"value": 5}'

'{"name": "Wilfredo"}'

JSON.parse()

JSON.parse()

JSON.parse()

any

Real

Tipo 'any'

any

Es un tipo, tal como string o number

Tipo

Significa que TS no tiene idea del tipo. No se puede hacer referencia a las propiedades del tipo.

Es un tipo, tal como string o number

Evita a toda costa variables de tipo 'any'

// Cuándo usar annotations
// 1) Una función que retorna el tipo 'any'
const json = '{"x": 10, "y": 20}';
const coordinates = JSON.parse(json);

console.log(coordinates); // {x: 10, y: 20}

Solución a 'any'

// Cuándo usar annotations
// 1) Una función que retorna el tipo 'any'
const json = '{"x": 10, "y": 20}';
const coordinates: {x: number; y: number} = JSON.parse(json);

console.log(coordinates); // {x: 10, y: 20}

Retrasar inicialización

// 2) Cuando declaramos una variable en una línea 
// y la inicializamos más tarde

let words = ['red', 'green', 'blue'];
let foundWord: boolean;

for(let i = 0; i < words.length; i++) {
  if(words[i] == 'green') {
    foundWord = true;
  }
}

Cuándo la inferencia no funciona

// 3) Cuando declaramos una variable con un tipo 
// que no puede ser inferido
let numbers = [-10, -1, 12];
let numberAboveZero: boolean | number = false; 

for (let i = 0; numbers.length; i++) {
  if(numbers[i] > 0) {
    numberAboveZero = numbers[i];
  }
}

Javascript

By Wilfredo Meneses

Javascript

  • 469