-
Notifications
You must be signed in to change notification settings - Fork 1
09. Typescript
TypeScript es un lenguaje de programación de código abierto, desarrollado y mantenido por Microsoft. Es un superconjunto(superset) de JavaScript, que esencialmente añade tipos estáticos y objetos basados en clases. Se transpila a JS (fácilmente usando parcel-bundler).
JS es dinamicamente y debilmente tipado.
- boolean: Valor verdadero o falso.
let muted: boolean = true;- number: Números.
let numerador: number = 42;- string: Cadenas de texto.
let saludo: string = `Me llamo ${nombre}`;- string[]: Arreglo del tipo cadena de texto.
let people: string[] = [];- :void, :never Funciones.
const noReturn = ():void => {};
const noFinish = ():never => {}; // not finish because is a infinity loop or throw exception.- :number | string Union.
let age = number | string;
age = 20;
age = '20';
age.toString(); // execute shared methods between both types
// Union type remove the security of the object type but can recover it with TypeGuards
// TYPE GUARDS
// to take advantage of union types without losing the security of type.
// the syntax of returned type conver this function in type guard
function isNumber(obj: number | string): obj is number {
return typeof obj == 'number';
}
function printAge(age: number | string) {
if(isNmber(age)) {
// security about the object is number;
} else {
// heree typescript know (infer) is a string
age.charAt(0);
}
}- :User & admin Intersection Types.
class User {
name: string;
}
class Admin {
permissions: number;
}
let user: User & Admin;
user.name = 'Carlos';
user.permissions = 5;
user = new User(); // error, because `user` is `User&Admin`
// TYPE ASSERTIONS
// is different from casting, you do not change the object, just override the compiler handle.
user = new User() as User&dmin;
// TYPE ALIASES
type numero = number;
let edad: numero;
type NumberOrString = number | string;
let age: NumberOrString;- :[string, number] Tuples. The difference with arrays, is the array only will accept one type
let tupla: [string, number];
// Error, because want string at [0] and number at [1]
tupla[0] = 20;
tupla[1] = '20';
tupla[2] = '1'; // this will accept union `string | number`- Array: Arreglo multi-tipo, acepta cadenas de texto o números.
// mutable
let peopleAndNumbers: Array<string | number> = [];
let peopleAndNumbers: (string | number)[] = [];
// inmutable
let peopleAndNumbers: ReadonlyArray<string | number> = [1, 'a', 'b'];
// const assertion
const config = ['http://hocalhost', 8000, '/api'] as const;
const config: readonly = ['http://hocalhost', 8000, '/api']; // cada item es readonly y su tipo es su propio valor- enum: Es un tipo especial llamado enumeración.
enum Color {
Rojo = "Rojo",
Verde = "Verde",
Azul = "Amarillo",
}
let colorFavorito: Color = Color.Azul;- any: Cualquier tipo.
let comodin: any = "Joker";
comodin = { type: "WildCard" }- unknown: Cualquier tipo, pero debes revisar el tipo antes de ejecutar cualquier método.
const stringify = (value: unknown): string => {
if (value instanfeof Date) {
return value.toISOString();
}
if (Array.isArray(value)) {
return JSON.stringify(value);
}
}- object: Del tipo objeto.
let someObject: object = { type: "WildCard" };
type Config = {
url: strin,
port: number,
path: string,
};
const config: Config = {
url: 'http://localhost',
port: 8000,
path: '/api'
}function add(a: number, b: number): number {
return a + b;
}
const sum = add(4, 25)
function createAdder(a: number): (number) => number {
return function (b: number) {
return a + b;
}
}
type Double = (x: number) => number;
interface Double = { (x: number): number }
const double: Double = (x) => x * 2;
const double2: Double = function (x) {
return x * 2;
}interface Rectangulo {
height: number,
width: number
}
let rect: Rectangulo = {
height: 4,
width: 3
}const appendToArr = <T, U> (
value: T,
arr: ReadonlyArray<U>,
): ReadonlyArray<T | U> => [...arr, value];
const arr = ['a', 1]; // const arr: (strung | number)[];
const arr2 = appendToArr(false, arr) // const arr2: (strung | number | boolean)[];JavaScript tradicional utiliza funciones y herencia basada en prototipos
class Greeter {
greeting: string; // propertie
// not return, only can exist 1
constructor(message: string) {
this.greeting = message;
}
greet() { // method
return"Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");Similares a las interfaces, pero estas si pueden tener implementación y las interfaces no. No pueden ser instanciadas, pero pueden tener métodos abstractos, que no deberían tener implementación si no que deben ser implementados por las sub-clases, como los metodos de las interfaces.
abstract class Greeter {
x: number;
y: number;
getCoords(): string { return `${this.x},${this.y}` }
abstract greet(name: string): string;
}
// Can't extends more classes.
class Hero extends Greeter {
// Doesn't need implement x,y, getCoords
greet(name: string) { return `Hello ${name}` }
}class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
/*
An alternative to this is implements Interface,
some class only can extends one class/abstract class
but can implements multiples interfaces
*/
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
/*
// to override methods from parent
move() {
super.move(10); // to call methods from parent can use super.anyMethod();
}
*/
}
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();Encapsulación: Ocultar implementación de la funcionalidad y sólo exponer una forma de mandar a llamar la implementación. No deberíamos tener atributos publicos. Ahí entran los métodos accesores (Getter/Setters).
Esto no es por seguridad, ** analogía ** no tienes que saber cómo funciona el motor, sólo necesitas la interfaz * volante, pedales * todo lo demás sucede internamente. Para sólo exponer la interfaz, la forma de usar el objeto y no sus detalles. Para crear objetos independientes más fáciles de re utilizar.
class Animal {
static url: string = 'http://google.com';
/*
To access this just need to use `Animal.url` no need instance objects to access this.
Is used when the info is from the class and no from the object. Only need 1 copy of this variable.
Will access to this variable from the class instead of object. can create static methods too,
and to call it just need use `Animal.method()` and is used when method does not need internal state.
*/
public name: string;
public constructor(theName: string) { this.name = theName; }
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}No se puede acceder desde afuera de su clase.
class Animal {
private _name: string;
constructor(theName: string) { this._name = theName; }
// Métodos accesores
get name() { return this._name; }
set name(name: string) { this._name = name; }
}
new Animal("Cat")._name; // Error: 'name' is private
new Animal("Cat").name; // Método accesorSimilar a private, añadiendo que las clases derivadas también pueden accederlo.
class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name); // every time you override constructor need call super();
this.department = department;
}
public getElevatorPitch() {
return`Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // errorPara agrupar identificadores (clases, interfaces, constantes, simbolos) bajo un mismo nombre. Para evitar colisiones.
namespace MY {
export class YouTube { };
export const url: string = 'http://google.com';
const private: string = '123';
}
let video: CF.YouTube = new CF.YouTube();