Typescript Curso
Typescript Curso
Notes 4
Compilar un archivo TS 5
Booleans - Booleanos 9
Numbers - Números 9
Tipo Any 10
Arrays - Arreglos 11
Tuples - Tuplas 12
Enum - Enumeraciones 12
Void - Vacío 14
Never - Nunca 15
Null - Undefined 16
Aserción de tipo 17
Funciones Básicas 18
1
Parámetros Opcionales de las Funciones 19
Parámetros REST 20
Tipo Función 21
Objetos básicos 23
Tipos personalizado 24
Características de ES6 29
Características: 29
Variables Let 29
Constantes - const 31
Templates Literales 33
Funciones Flecha 33
Desestructuración de Objetos 36
Nuevo Ciclo - For Of 37
Clases en ES6 38
Desestructuración de Arreglos 40
Clases en TypeScript 41
Definición de una clase básica en TypeScript 41
Constructores 41
Propiedades públicas, privadas y protegidas 42
Métodos públicos, privados y protegidos. 43
Herencia, super y definición de propiedades en el constructor 44
Gets y Sets 45
Métodos y propiedades estáticos 49
Clases Abstractas 50
2
Constructores privados 51
Interfaces 53
Interfaz Básica 53
Propiedades Opcionales 54
Métodos en la Interfaz 55
Interfaces en las Clases 56
Interfaces para las funciones 56
Notes 57
Módulos 59
Genéricos - Generics 61
Introducción a los Genéricos 61
Creando funciones genéricas 61
Ejemplo de función genérica en acción 62
Arreglos Genéricos 64
Clases genéricas 64
Decoradores 67
Introducción a los decoradores 67
Decoradores de clases 67
Decoradores de fábrica - Factory decorators 68
3
Notes
Las interfaces y los tipos son ignorados al momento de ser compilados a JavaScript
tsc -v
Colonize
1. shift + enter: Insertar punto y coma al final de la línea y continuar en la misma línea
2. alt + enter: Insertar punto y coma al final de la línea y continuar en la nueva línea
3. ctrl + alt + enter: Insertar punto y coma y permanecer en la misma posición
4
Compilar un archivo TS
Para entenderlo mejor miremos el siguiente ejemplo:
Creamos una carpeta con el nombre TypeScript, y la abrimos con visual studio code, dandole clic
derecho OPEN WITH CODE.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<script src="app.js"></script>
</body>
</html>
console.log("hola mundo");
tsc nombre_del_archivo
5
En resumen los navegadores web no pueden correr el código TypeScript directamente, necesita ser
traducido a su versión JavaScript para que el navegador web lo pueda interpretar. Mediante el
comando tsc lo convertimos de TypeScript a JavaScript.
tsc nombre_del_archivo -w
tsc -init
tsc -w
6
Introducción a los tipos de datos
STRINGS
"Maria perez"
'Mazda'
`<h1>Hola mundo</h1>`
NÚMEROS
pi = 3.14159265359
salario = 1500.00
entero = 1
BOOLEANOS
Verdadero (true)
Falso (false)
NULL Y UNDEFINED
numero = null
persona = undefined
OBJETOS LITERALES
var persona = {
nombre: "Stiven",
edad: 26
}
propiedades como la que dice nombre y métodos que serían funciones dentro de esa persona.
7
CLASES
class Persona {
nombre;
edad;
}
FUNCIONES
function saludar() {
return "hola!";
}
a pesar de que pareciera raro decir que una función es un tipo de dato, mentalizarse que pueden
definir una variable de tipo función.
ES POSIBLE
Crear tipos nuevos, a los que ya trae TS por defecto.
Documentación: http://www.typescriptlang.org/docs/handbook/basic-types.html
8
Booleans - Booleanos
Numbers - Números
Note: en Javascript toda variable que no está asignada, tienen el valor por defecto undefined. Esto
se puede controlar, podemos decirle al TS que nos avise cuando las variables no tengan valores
dentro.
9
si yo escribo batman. me salen todos los métodos que tiene un string. esto es de gran ayuda a la
hora de programar.
La mejor manera para hacer este tipo de uniones de strings es usar los templates literales del
EMC6
let concatenar: string = "Los héroes: " + batman + ", " + linternaVerde;
let concat: string = `Los héroes son: ${ batman }, ${ linternaVerde } `;
console.log( concat );
Tipo Any
Una variable de tipo Any puede ser cualquier cosa
vengador = 150.5555;
console.log( vengador.toFixed(2));
10
vengador = true;
console.log( vengador );
console.log( existe );
imprime:
Arrays - Arreglos
los arreglos van a ser igual que en JS solo que le podemos definir que tipo de dato tiene.
TS va a deducir que es un arreglo de número por el contenido, vemos que al hacer un push de un
string TS nos arroja un error:
pero esto no es buena práctica, no tiene sentido que usemos TS para hacer todo de este calibre.
si yo quiero decir que esto es un arreglo de números, tengo que poner [] junto al tipo.
11
Al definir su tipo tengo como sugerencias todas las características que tiene un arreglo :D.
Tuples - Tuplas
Las tuplas es un tipo de dato que no existe en JS , pero tienen una forma muy parecida a lo que es
un arreglo.
Funciona también para poder hacer lectura de los datos no solo como tupla sino también como
tercios, cuartos Etc.
Enum - Enumeraciones
Pensemos en este tipo de dato para dar un sentido lógico a unos números. pensemos que estamos
trabajando en un aplicación que reproduzca audio:
enum Volumen{
min,
medio,
max
}
12
let audio: number = Volumen.min;
console.log( audio );
console.log( Volumen );
enum Volumen{
min = 1,
medio,
max = 10
}
console.log( audio );
console.log( Volumen );
console.log( Volumen[2] );
13
note:
Void - Vacío
es el opuesto a any, void es ningún tipo, vacío.
sabemos que en JS una función que no regresa nada realmente si regresa algo, un Undefined.
14
si yo quiero que una función no regrese nada y solo ejecute algo.
si yo pongo dos puntos, le estoy diciendo que va a retornar.
Note que me muestra error al tratar de retornar algo, cuando está ya definido que no retorna
nada.
TS interpreta que Void que no hay un valor de retorno, si una función de tipo void le colocaremos
un return, este presenta error ya que no está esperando nada
(()=>{
function callBatman():void{
return 1;
}
const a = callBatman();
console.log(a);
})()
Never - Nunca
representa un valor que nunca puede suceder.
es por decirlo así, algo que sucede en nuestro programa y si retorna un never, o si tenemos una
función con un never, quiere decir que ya falló nuestra aplicación.
15
Null - Undefined
Pero note que esto sí está permitido. El primer ejemplo ocurre lo mismo si definimos la variable de
tipo null. funcionan parecido.
En este ejemplo vemos que si acepta el cambio de tipo para este caso
16
Si en el tsconfig.json descomentamos la opción, strictNullChecks ahora si nos generará error:
por que sin está restricción si pasa?, por que el null y el undefined son valores permitidos para
estas variables.
Aserción de tipo
// Aserciones de Tipo
var poder: any = "100";
var largoDelPoder: number = (<string>poder).length;
console.log( largoDelPoder );
note: con el <string> le estoy diciendo a TS que trabaje la variable como un string, así
permitiéndonos tener todas las opciones del string (la ayuda de autocompletar).
Permitirme poder usar cualquier variable de otro tipo, y decirle a TS confía en mí, yo sé lo que
estoy haciendo.
17
Funciones Básicas
function imprime_heroe():string{
return heroe;
}
console.log( imprime_heroe() );
console.log( activar_batisenal() );
console.log( nombre );
18
Parámetros Opcionales de las Funciones
En JS todos los parámetros son opcionales. Pero en TS necesitamos ponerles un ?
if ( apellido ) {
return nombre + ' ' + apellido;
} else {
return nombre;
}
}
console.log( nombre );
apellido es un parámetro opcional, y para evitar que nos retorne un undefined, hacemos un
condicional que verifique si existe.
19
function nombreCompleto ( nombre: string,
apellido: string,
capitalizado: boolean = true): string {
if ( capitalizado ) {
return capitalizar(nombre) + ' ' + capitalizar(apellido);
} else {
return `${nombre} ${apellido}`;
}
}
console.log( nombre );
Vemos que solo le definimos un valor al parámetro para que este sea al valor por defecto al no ser
ingresado en el llamado de la función.
Parámetros REST
problema: Tenemos una función que debe ser capaz de recibir n cantidad de parámetros, los que
sean necesarios
20
console.log( iroman );
El parámetro nombre está definido como obligatorio para la función en este caso.
¿Cómo definimos ese tal parámetro REST? con la siguiente función: ...losDemasParametros
join es una función de los arreglos de JS donde se le ingresa con que se quieren unir, en este caso
con un espacio.
Note:
Tipo Función
() =>
donde lo que va dentro de los paréntesis son los parámetros, y lo que va después de => es el tipo
de valor que retorna. ejemplo:
21
let miFuncion: (x: number, y: number) => number ;
lo que le estamos diciendo a TypeScript es que la variable miFuncion es de tipo función, y que
tiene como parámetros X y Y que son de tipo number, y además retorna un valor de tipo number.
ejemplo de utilización:
miFuncion = sumar;
console.log( miFuncion(5,5) );
note que la función a la que se iguala miFuncion, no tiene que tener el mismo nombre en los
parámetros, pero sí deben ser la misma cantidad y el mismo tipo, al igual que tienen que tener el
mismo tipo de valor de retorno.
22
Objetos básicos
let flash = {
nombre: "Barry Allen",
edad: 24,
poderes: ["correr muy rápido", "viajar en el tiempo"]
}
el definir este objeto de esta manera, y yo quiero re asignar los valores debo cumplir esta
estructura.
23
}
flash.getNombre();
ES5:
var flash = {
nombre: "Barry Allen",
edad: 24,
poderes: ["correr muy rápido", "viajar en el tiempo"],
getNombre: function () {
return this.nombre;
}
};
flash.getNombre();
Tipos personalizado
Estoy creando una definición de un tipo.
type Heroe = {
nombre: string,
edad: number,
poderes: string[],
getNombre:()=>string
}
24
poderes: ["correr muy rápido", "viajar en el tiempo"],
getNombre() {
return this.nombre;
}
}
loquesea = 10;
Utilizaremos la instrucción de JS typeof, el cual nos regresa un string con el tipo de dato:
25
let cosa: any = 123;
console.log(typeof cosa);
guardas el archivo.
26
ahora al compilar el archivo de TS, se creará un archivo .js.map y al ejecutarlo en el navegador
podremos ver el archivo .ts en la opción de Source:
puedo hacer un breakpoint o punto de quiebre dando clic en el número de la línea, lo que hará
que al ejecutarse se pause justo ahí.
27
Remover los comentarios al compilar
En el archivo tsconfig, buscamos el comando removeComments, lo descomentamos y ponemos en
true.
de esta manera, todos los comentarios que hayamos hecho en nuestro archivo de TS, no
aparecerán o estarán en el archivo de JS al compilar, sería como un ignoreme los comentarios.
Note: si tenemos el archivo tsconfig podemos omitir el nombre del archivo y solo poner tsc
--removeComments.
Si al tener esta opción activada queremos que un comentario no sea ignorado lo ponemos con un
/*!
28
Características de ES6
Características:
● Mejora en el ámbito de las variables
● Adición de constantes
● Templates Literales
● Funciones de flecha (lambda)
● Desestructuración de objetos y arreglos
● Nuevos ciclos
● Clases
● Entre otras cosas
Variables Let
Declarando variables con la palabra reservada let
podemos utilizar let en todos los lugares donde estaba anteriormente var
if (true) {
console.log(nombre);
29
Pero si utilizamos let:
if (true) {
console.log(nombre);
¿por qué no salió Bruce?, al crear una variable let la crea en un ámbito específico, es decir, si yo
creo la variable en el scope global y yo entro y creo una variable dentro del if, no va a poner la
variable en el scope global de nuevo, simplemente va a crearse un ámbito especial. Estas llaves
(del if) van a decir que hasta ahí van a vivir las variables que ustedes pongan allí adentro.
esto es particularmente útil porque podrían usar el mismo nombre de variable sin tener ningún
error.
Otra característica de let, es que ustedes no pueden re declarar variables en el mismo ámbito
if (true) {
30
console.log(nombre);
Constantes - const
El ES6 incorpora lo que son las constantes, que es un dato que no puede mutar una vez definido.
pero… ¿por qué en el caso anterior si es posible?, porque estamos en un diferente scope, aquí es
otro ámbito totalmente de la variable, ahí si lo permite.
31
vemos que este caso también es permitido a pesar de que la constante en teoría está cambiando
de valor, realmente cuando se hace un ciclo for en el ES6 siempre va creando un nuevo ámbito por
cada scope, por eso es que lo permite.
const OPCIONES = {
estado: true,
audio: 10,
ultima: "main"
}
OPCIONES.estado = false;
OPCIONES.audio = 1;
console.log( OPCIONES );
Note:
32
Templates Literales
Son Strings que soportan multi línea, y permiten incrustar variables o el producto de funciones
dentro del mismo String.
function getNombres():string{
return `${nombre1} ${nombre2}`;
}
console.log( mensaje );
Funciones Flecha
cómo representamos una función normal a una de flecha:
función normal:
33
function sumar(a,b){
return a + b;
}
console.log( sumar(2,2) );
Función flecha:
let sumar = (a,b) => a+b;
console.log( sumar(2,2) );
si tuviéramos más líneas, podríamos abrir llaves, y dentro lo que equivale al cuerpo de la función:
let sumar = (a,b) => {
console.log("vamos a sumar!");
return a + b;
};
pero cuando es solo una instrucción basta con hacerlo de la primera forma.
Otro ejemplo:
console.log( darOrden_hulk("smash!!!") );
console.log( darOrden_hulk("smash!!!") );
34
miremos este ejemplo donde las funciones de flecha si son útiles.
let capitan_america = {
nombre: "Hulk",
darOrden_hulk: function() {
setTimeout(function(){
capitan_america.darOrden_hulk();
supongamos que hulk es un poco lento de la cabeza y la orden que recibe la ejecuta un segundo
después (setTimeout).
al segundo aparece nuestro mensaje, pero fijense que es undefined smash!!!, ¿por qué undefined?
cuando usemos funciones asíncronas o trabajamos con cosas como el ejemplo que crea un nuevo
contexto de una función dentro de una función, el puntero del this (en this.nombre) se pierde o
apunta a otra cosa, en este caso está apuntando al objeto global. Este código ya no funciona.
entonces utilicemos la función de flecha para evitar que this mute, las funciones de flecha no
cambian el objeto this, en otras palabras el this dentro de la función de flecha va a ser el mismo
this del contexto anterior.
let capitan_america_ = {
nombre: "Hulk",
darOrden_hulk: function() {
35
setTimeout( ()=>console.log( this.nombre + " smash!!!" ), 1000);
}
}
capitan_america.darOrden_hulk();
note: como solo realiza una sola instrucción no hace falta ponerle llaves.
Desestructuración de Objetos
suponga que necesita extraer los avenger dentro de ese objeto:
let avengers = {
nick: "Samuel Jackson",
ironman: "RObert Downey Jr",
vision: "Paul Bettany"
}
let avengers = {
nick: "Samuel Jackson",
ironman: "RObert Downey Jr",
vision: "Paul Bettany"
36
}
primero utilizo la palabra reservada let para hacer el espacio de memoria. Luego llaves, las llaves es
para decir que quiero crear, en este caso quiero crear las variables nick, ironman y vision. ¿Pero de
dónde voy a extraer esa data?, ponemos el igual y lo extraemos del objeto avengers. Eso es todo.
let thor = {
nombre: "Thor",
arma: "Mjolnir"
};
let ironman = {
nombre: "Ironman",
arma: "Armorsuit"
};
let capitan = {
nombre: "Capitán América",
arma: "Escudo"
};
si yo quisiera barrer todas las personas que están dentro de ese arreglo
en ES5:
37
let avenger = avengers[i];
console.log( avenger.nombre, avenger.arma );
}
// tradicional
for ( let i = 0; i <= avengers.length - 1; i++ ){
let avenger = avengers[i];
console.log( avenger.nombre, avenger.arma );
}
Clases en ES6
class Avenger {
constructor(nombre, poder) {
this.nombre = nombre;
this.poder = poder;
}
}
console.log(hulk);
38
Es posible en las clases heredar las características a otra clase hija.
class Avenger {
constructor(nombre, poder) {
this.nombre = nombre;
this.poder = poder;
}
}
constructor(nombre, poder){
super( nombre, poder );
this.vuela = true;
}
}
console.log( falcon );
39
Desestructuración de Arreglos
// Desestructuración de arreglos?
let versiones = ["Spider-Man 2099", "Spider-Girl", "Ultimate Spider-Man"];
de la siguiente forma:
40
Clases en TypeScript
class Avenger {
puedePelear:boolean;
peleasGanadas:number;
Constructores
Un constructor es una simple función que es ejecutada cuando se crea una nueva instancia de ese
objeto.
class Avenger {
puedePelear:boolean = false;
peleasGanadas:number = 0;
41
this.equipo = equipo;
this.nombreReal = nombreReal;
}
console.log(antman);
el constructor del TypeScript es mucho más poderoso que el constructor del ES6.
inicializar las propiedades con un valor por defecto puede hacerse perfectamente de esta forma.
class Avenger {
42
}
class Avenger {
public bio():void {
let mensaje:string = `${this.nombre} ${this.nombreReal} ${this.equipo}`;
console.log(mensaje);
}
public cambiarEquipoPublico(nuevoEquipo:string):boolean{
return this.cambiarEquipo(nuevoEquipo);
}
43
private cambiarEquipo(nuevoEquipo:string):boolean{
class Avenger{
protected getNombre():string{
console.log("get nombre avenger (protegido)");
return this.nombre;
}
44
constructor( a:string, b:string ){
console.log("Constructor Xmen llamado");
super(a,b);
}
public getNombre():string{
console.log("get nombre xmen (público)");
return super.getNombre();
}
}
console.log( ciclope.getNombre() );
Gets y Sets
es una forma de acceder a las propiedades de una manera controlada.
definir una variable con un guión bajo es una convención para definir que la variable (propiedad)
es privada y sólo se usará dentro de la clase.
para hacer el llamado de esta función, no esperen hacerlo como un método:
45
class Avenger {
get nombre():string{
return this._nombre
}
}
console.log( ciclope.nombre );
class Avenger {
get nombre():string{
if ( this._nombre ){
return this._nombre
}else {
return "No tiene un nombre el avenger"
}
}
}
console.log( ciclope.nombre );
46
con los sets es lo mismo, por defecto estos no regresan nada, aunque ustedes pueden regresar si
lo hizo o no lo hizo.
class Avenger {
get nombre():string {
return this._nombre;
}
set nombre(nombre:string){
this._nombre = nombre;
}
}
ciclope.nombre = "Ciclope";
console.log( ciclope.nombre );
class Avenger {
get nombre():string {
return this._nombre;
}
47
set nombre(nombre:string){
ciclope.nombre = "Lee";
console.log( ciclope.nombre );
si el tamaño del nombre es menor o igual a 3 entonces hago un return, osea me salgo.
class Avenger {
private _nombre:string;
constructor( nombre?:string ) {
this._nombre = nombre;
}
get nombre():string {
return this._nombre;
}
set nombre(nombre:string){
48
throw new Error("El nombre debe tener al menos 4 caracteres.");
}
this._nombre = nombre;
}
}
ciclope.nombre = "Lee";
console.log( ciclope.nombre );
class Xmen{
constructor() {
}
si yo quisiera acceder al nombre de Wolverine tendría que crear un instancia de la clase Xmen
49
console.log( wolverine.nombre );
class Xmen{
constructor() {
}
static crearXmen(){
console.log("Se creó usando un método estático");
return new Xmen();
}
console.log( Xmen.nombre );
Clases Abstractas
Cuando utilizo abstract no puedo crear instancias de la clase:
50
abstract class Mutantes{ // X-MEN
Entonces esto para qué diablos sirve. Es utilizado para crear como un molde de las clases y
heredarlo a otras clases.
console.log( wolverine);
Constructores privados
51
52
Interfaces
Interfaz Básica
interface Xmen {
nombre: string,
poder: string
}
Con CamelCase
let wolverine:Xmen = {
nombre: "Wolverine",
poder: "Regeneración"
};
enviarMision( wolverine );
53
Propiedades Opcionales
interface Xmen {
nombre: string,
poder?: string
}
if(xmen.poder){
console.log(`Necesitamos ${xmen.poder}`);
}
let wolverine:Xmen = {
nombre: "Wolverine",
poder: "Regeneración"
};
enviarMision( wolverine );
54
Métodos en la Interfaz
Hay que especificar (si los tiene) los parámetros, y el retorno.
interface Xmen {
nombre: string,
regenerar( nombreReal:string ):void
}
No estamos diciendo que es lo que tiene que hacer la función, puede ser lo que sea, pero recibe y
regresa lo especificado.
interface Xmen {
nombre: string,
regenerar?( nombreReal:string ):void
}
Ejemplo
xmen.regenerar("Logan");
let wolverine:Xmen = {
nombre: "Wolverine",
regenerar(x:string){
console.log("Se ha regenerado " + x);
}
};
55
enviarMision( wolverine );
interface Xmen{
nombre:string;
nombreReal?:string;
regenerar( nombreReal:string ):void;
}
interface DosNumerosFunc{
( num1:number, num2:number ) : number
}
56
let sumar:DosNumerosFunc;
sumar = function(a:number,b:number){
return a + b;
}
let restar:DosNumerosFunc;
restar = function(numero1:number,numero2:number){
return numero1 - numero2;
}
Note que el código para definir la interfaz es muy parecido pero no es igual, a la forma vista en
clases anteriores.
La diferencia es que aquí no vamos a definir propiedades, vamos a definir únicamente un método,
solo uno.
Notes
es posible heredar interfaces con la palabra extends :
interface Carro{
llantas:number;
modelo:string;
}
var volvo:Volvo = {
llantas: 4,
modelo:"sedan",
57
seguro:true
}
58
Módulos
TypeScript nos da la posibilidad de crear aplicaciones que permitan importar funciones, clases,
propiedades, variables o constantes de otros archivos del proyecto sin necesidad de agregar las
referencias en nuestras páginas HTML.
Los módulos es una forma de programar que brinda grandes funciones a la programación web.
59
Para obtener todos los módulos (osea propiedades y métodos con la palabra export) del archivo
textos:
para entender todo esto mejor, mirar los dos últimos videos de la sección de módulos.
60
Genéricos - Generics
JavaScript por ser un lenguaje dinámico, conlleva a tener varios problemas por esa misma
flexibilidad, pero a su vez, permite resolver problemas de una forma muy sencilla. Esta sección está
destinada a comprender cómo mantener la programación estructurada del TypeScript con el
dinamismo de JavaScript.
los genéricos es algo que me va a permitir a mi trabajar con cualquier tipo de dato, y aprovechar
las ventajas que tiene TypeScript para que me ayude con la autocompletación y posibles errores
que yo pueda cometer a la hora de escribir o a la hora de manejar la data.
61
function regresar<T>( arg:T ){
return arg;
}
Es un estándar que nuestra función genérica tenga esa T, esta T puede ser cualquier cosa pero es
una convención usar la T.
62
function functionGenerica<T>( arg:T ){
return arg
}
type Heroe = {
nombre:string;
nombreReal:string;
}
type Villano = {
nombre:string;
poder:string;
}
Observe que el siguiente objeto puede ser de cualquiera de los dos tipos descritos arriba:
let deadpool = {
nombre: "Deadpool",
nombreReal: "Wade Winston Wilson",
poder: "regeneración",
};
63
mandando el tipo antes de los paréntesis.
Con esto podemos tener o manejar una flexibilidad y todavía tener el control de TypeScript a la
mano.
Arreglos Genéricos
para crear un arreglo genérico basta con hacer el siguiente código:
Clases genéricas
¿Como controlar el tipo que estoy enviando?
Mi función entre los tipos genéricos, solo puede recibir números o strings.
64
en la declaración también se puede definir cuál quieres que se acepte, en el ejemplo se define que
acepte ambos tipos, mientras esté permitido en la definición de la clase.
por ejemplo si agrego un booleano, me generará un error por que no está permitido en mi clase
genérica.
ustedes pueden anticiparse que pueden ser números o pueden ser strings tanto en la clase como a
la hora de instanciar la clase.
cuadrado.base = "10";
cuadrado.altura = 10;
console.log( cuadrado.area() );
65
66
Decoradores
Los decoradores son una característica nueva en el TypeScript que cada vez es más utilizada por
otros frameworks como Angular 2. Pero vamos a aprender a utilizar decoradores en nuestros
proyectos.
Es una cosita que se pone antes de una función, antes de un método o una propiedad y nos va a
permitir expandir su funcionalidad agregando cosas nuevas. Pueden hacer hasta inclusive mutar
completamente la función.
Decoradores de clases
Tenemos una clase sencilla:
class Villano {
constructor( public nombre:string ){
}
}
Los decoradores recordemos que son una función. Los decoradores para las clases
automáticamente al estar adjunto a una clase lo que hacen es enviar como parámetro el
constructor de la clase:
@consola
class Villano {
constructor( public nombre:string ){
67
}
}
pero para que esto compile debemos activar la opción de nuestro tsconfig.json
"experimentalDecorators": true,
Qué pasaría si yo quisiera que mi función consola, imprima el constructor o no lo imprima, osea yo
tengo que decirle si yo quiero imprimirlo o no quiero imprimirlo, aquí es donde viene el Factory
Decorator.
mi decorador de fábrica será imprimirConsola, el cual recibe un booleano y regresa una función.
si imprimir es verdadero entonces quiero hacer el return de la función consola, pero sin los
parentesis, no quiero ejecutar la función, solo quiero retornar la función que sirve como un
decorador de clase o decorador de lo que quiera usar.
68
// Decorador de Clase
function consola( constructor:Function ){
console.log( constructor );
}
// Decorador Factory
function imprimirConsola( imprimir:boolean ):Function {
if ( imprimir ) {
return consola;
} else {
return null;
}
}
@imprimirConsola(true)
class Villano {
constructor( public nombre:string ){
}
}
69