Sei sulla pagina 1di 154

mb

Yo:
TypeScript

J.C. Lama
1

Esta pgina se ha dejado en blanco intencionalmente.

http://creativecommons.org/licenses/by-sa/3.0/es/

Jos Carlos Lama Ponce


Primera edicin: octubre 2014
Versin TypeScript: 1.1.0.1

A mis padres, mis hermanos y mi pareja.

Esta pgina se ha dejado en blanco intencionalmente.

Esta pgina se ha dejado en blanco intencionalmente.

10

0.

INTRODUCCIN.....................................................................................12
0.1
0.2
0.2.1
0.2.2
0.2.3
0.3
0.3.1
0.3.2
0.3.3
0.3.4

1.

A QUIN VA DIRIGIDO ESTE LIBRO?..............................................................................12


JAVASCRIPT.............................................................................................................. 12
Historia......................................................................................................... 12
mbito de ejecucin.....................................................................................12
Compatibilidad con navegadores..................................................................13
TYPESCRIPT............................................................................................................. 13
Por qu TypeSript?......................................................................................13
Qu es y no es TypeScript.............................................................................13
TS es JS......................................................................................................... 14
Requisitos..................................................................................................... 14

GENERALIDADES...................................................................................16
1.1
1.2
1.3
1.4
1.5

2.

SENTENCIAS............................................................................................................. 16
SENSIBLE A LAS MAYSCULAS......................................................................................16
PALABRAS RESERVADAS.............................................................................................. 16
UNICODE................................................................................................................. 16
COMENTARIOS.......................................................................................................... 16
CMO EMPEZAR....................................................................................18

2.1
2.2
2.3
2.4
3.

INTRODUCCIN......................................................................................................... 18
EDITORES................................................................................................................ 19
DIVIDIR EL PROYECTO.................................................................................................21
LIBRERAS EXTERNAS.................................................................................................. 22
DEPURACIN.........................................................................................24

3.1
3.2
3.3
3.4
3.5
4.

INTRODUCCIN......................................................................................................... 24
LA CONSOLA............................................................................................................ 24
DEPURANDO TS........................................................................................................ 25
PUNTOS DE RUPTURA................................................................................................. 26
EVALUADOR DE EXPRESIONES......................................................................................27
VARIABLES............................................................................................30

4.1
4.2
4.3
4.4
4.5
5.

INTRODUCCIN......................................................................................................... 30
NOMBRES DE VARIABLES.............................................................................................30
INICIALIZACIN.......................................................................................................... 30
MBITO DE UNA VARIABLE........................................................................................... 31
CONSTANTES............................................................................................................ 31
TIPOS...................................................................................................32

5.1
5.2
5.2.1
5.3
5.3.1
5.3.2
5.3.3
5.3.4
5.3.5
5.3.6
5.3.7
5.4
5.5
5.5.1

VARIABLES CON TIPO.................................................................................................32


TIPOS PRIMITIVOS Y ENVOLTURA....................................................................................32
Inicializacin literal.......................................................................................33
OTROS TIPOS........................................................................................................... 35
Void............................................................................................................... 35
Null............................................................................................................... 35
Undefined..................................................................................................... 35
Enum............................................................................................................ 35
Function........................................................................................................ 35
Array............................................................................................................. 36
Object........................................................................................................... 36
TIPOS NOMBRADOS Y REFERENCIA.................................................................................37
INFERENCIA DE TIPOS................................................................................................. 37
Inferencia bsica........................................................................................... 37

12

5.5.2
5.6
5.6.1
5.6.2
5.6.3
5.6.4
5.6.5
5.7
5.8
6.

Expresiones tipadas por el contexto.............................................................37


EL

MEJOR TIPO COMN............................................................................................... 38

Any como tipo general..................................................................................38


{}................................................................................................................. 38
Entre primitivos............................................................................................ 38
Entre primitivos y envolturas........................................................................39
Entre tipos referencia...................................................................................39
TYPEOF.................................................................................................................... 39
EL USO DE LA MEMORIA.............................................................................................. 40

OPERADORES........................................................................................42
6.1
6.1.1
6.1.2
6.1.3
6.1.4
6.1.5
6.1.6
6.2
6.2.1
6.2.2

OPERADORES UNARIOS............................................................................................... 42
Operadores ++ y --.......................................................................................42
Operadores +, ............................................................................................ 43
Operador ~................................................................................................... 43
Operador !.................................................................................................... 43
Operador delete............................................................................................ 44
Operador void............................................................................................... 44
OPERADORES BINARIOS.............................................................................................. 44
Operador de asignacin................................................................................44
Operadores lgicos.......................................................................................45
6.2.2.1
6.2.2.2
6.2.2.3

6.2.3

Operadores aritmticos................................................................................47
6.2.3.1
6.2.3.2
6.2.3.3

6.2.4
6.2.5

Operadores lgicos bit a bit................................................................................... 48


Operadores << y >>............................................................................................. 48

Operadores relacionales...............................................................................48
6.2.5.1
6.2.5.2
6.2.5.3

7.

Operadores + y -.................................................................................................... 47
Operadores * y /..................................................................................................... 47
Operador %............................................................................................................ 47

Operadores de bits.......................................................................................48
6.2.4.1
6.2.4.2

6.2.6
6.2.7
6.2.8

false en TS............................................................................................................. 45
Operador AND........................................................................................................ 45
Operador OR.......................................................................................................... 46

Operadores <, >, <=, >=,..................................................................................... 48


Operadores == y !=.............................................................................................. 49
Operadores === y !==......................................................................................... 49

Operador + de concatenacin......................................................................51
Operador in................................................................................................... 51
Operador condicional terciario......................................................................51

CONTROL DEL FLUJO..............................................................................54


7.1
7.2
7.2.1
7.2.2
7.3
7.3.1
7.3.2
7.3.3
7.3.4
7.4
7.4.1
7.4.2

8.

INTRODUCCIN......................................................................................................... 54
SELECTIVAS.............................................................................................................. 54
if................................................................................................................... 54
switch........................................................................................................... 55
ITERATIVAS............................................................................................................... 56
while............................................................................................................. 56
do-while........................................................................................................ 56
for................................................................................................................. 56
for-in............................................................................................................. 57
SENTENCIAS TILES PARA LOS BUCLES...........................................................................57
break............................................................................................................ 57
continue........................................................................................................ 58

FUNCIONES...........................................................................................60
8.1
8.2

INTRODUCCIN......................................................................................................... 60
DECLARACIN........................................................................................................... 60

14

8.3

PARMETROS DE UNA FUNCIN....................................................................................60


Parmetros opcionales y por defecto............................................................61
Ms parmetros............................................................................................ 61
Parmetros por valor o por referencia..........................................................62

8.3.1
8.3.2
8.3.3

8.3.3.1
8.3.3.2
8.3.3.3

8.4
8.5
8.6
8.7

VALORES DE RETORNO............................................................................................... 64
INVOCANDO FUNCIONES.............................................................................................. 64
SOBRECARGA........................................................................................................... 65
FUNCIONES ANNIMAS...............................................................................................66
Expresiones lambda (funciones flecha).........................................................66
Tipado literal de una funcin........................................................................67
Tipado mediante objetos literales.................................................................67
Definicin de funcin por parmetro.............................................................68
Contexto....................................................................................................... 68
Funciones annimas autoejecutables...........................................................69
FUNCIONES QUE DEVUELVEN FUNCIONES........................................................................69
FUNCIONES ESPECIALIZADAS........................................................................................ 70
COMPARANDO FUNCIONES........................................................................................... 70

8.7.1
8.7.2
8.7.3
8.7.4
8.7.5
8.7.6
8.8
8.9
8.10
9.

Por valor................................................................................................................. 62
Por referencia......................................................................................................... 63
Paso por copia referencial...................................................................................... 63

ENUMERADOS.......................................................................................72
9.1
9.2

INTRODUCCIN......................................................................................................... 72
OBTENIENDO EL NOMBRE DEL VALOR.............................................................................72

10.

CLASES.................................................................................................74

10.1
10.2
10.3
10.4
10.4.1

QU ES UNA CLASE.................................................................................................... 74
CREACIN DE CLASES................................................................................................74
CONSTRUCTORES...................................................................................................... 75
ESTADO Y COMPORTAMIENTO.......................................................................................75
El estado....................................................................................................... 75

10.4.1.1 Otra forma de declarar atributos............................................................................ 76

10.4.2
10.4.3

El comportamiento........................................................................................ 77
Operador this................................................................................................ 78

10.4.3.1 Contexto................................................................................................................ 78

10.5
ENCAPSULAMIENTO.................................................................................................... 80
10.5.1
Getters y setter implcitos.............................................................................82
10.6
HERENCIA................................................................................................................ 83
10.6.1
El operador super......................................................................................... 83
10.6.2
Sobreescritura.............................................................................................. 85
10.6.2.1 Sobreescritura de mtodos.................................................................................... 85

10.7
AGREGACIN Y COMPOSICIN......................................................................................86
10.8
POLIMORFISMO......................................................................................................... 87
10.9
CONVERSIN DE TIPOS (CASTING)................................................................................87
10.10
LIGADURA DINMICA.................................................................................................. 89
10.11
INSTANCEOF............................................................................................................. 90
10.12
ESTTICOS............................................................................................................... 90
10.12.1
Constantes mediante estticos.....................................................................91
10.13
CLASES LITERALES..................................................................................................... 92
10.14
LAS PARTES DE UNA CLASE..........................................................................................92
10.15
OBJETOS DINMICOS.................................................................................................. 93
11.
11.1
11.2
11.3

INTERFACES..........................................................................................95
INTRODUCCIN......................................................................................................... 95
DECLARACIN E IMPLEMENTACIN.................................................................................95
HERENCIA................................................................................................................ 96

16

11.4
11.5
11.6
11.7
12.
12.1
12.2
12.3
12.4
12.5
13.
13.1
13.2
13.3
13.4
13.5
14.
14.1
14.2
14.3
14.4
14.5
15.

INTERFACES LITERALES................................................................................................97
INTERFACES COMO FUNCIONES.....................................................................................97
FUSIONANDO INTERFACES............................................................................................98
COMPROBAR SI UNA CLASE IMPLEMENTA UNA INTERFAZ.....................................................98
GENRICOS.........................................................................................100
INTRODUCCIN....................................................................................................... 100
RESTRICCIONES EN LOS PARMETROS..........................................................................101
GENRICOS EN INTERFACES.......................................................................................102
FUNCIONES GENRICAS.............................................................................................103
COMPARANDO GENRICOS......................................................................................... 103
TIPADO ESTRUCTURAL.........................................................................104
MS SOBRE LA COMPARACIN DE OBJETOS...................................................................104
COMPARANDO CLASES.............................................................................................. 104
COMPARANDO INTERFACES........................................................................................105
CLASES IMPLEMENTANDO OTRAS CLASES......................................................................106
INTERFACES HERENDANDO DE CLASES..........................................................................107
CONTROL DE ERRORES.........................................................................108
INTRODUCCIN....................................................................................................... 108
TIPOS DE ERRORES.................................................................................................. 108
LANZANDO ERRORES................................................................................................109
LANZANDO ERRORES MANUALMENTE...........................................................................110
FINALLY................................................................................................................. 110
DOM................................................................................................... 112

15.1
INTRODUCCIN....................................................................................................... 112
15.2
DOCUMENT............................................................................................................ 112
15.2.1
Seleccionar elementos................................................................................112
15.2.1.1 getElementById()................................................................................................. 113
15.2.1.2 getElementsByTagName().................................................................................... 113

15.3
15.4
15.5
16.

CREAR ELEMENTOS.................................................................................................. 113


ELIMINAR ELEMENTOS...............................................................................................113
ACCESO A LOS ATRIBUTOS......................................................................................... 114
EVENTOS............................................................................................116

16.1
INTRODUCCIN....................................................................................................... 116
16.2
EVENTOS VISUALES.................................................................................................. 116
16.2.1
Fase de captura.......................................................................................... 116
16.2.2
Fase de objetivo.......................................................................................... 117
16.2.3
Fase de burbuja.......................................................................................... 117
16.2.4
Aadir respuesta a los eventos...................................................................117
16.2.5
Parmetros de los handlers........................................................................118
16.2.6
Target y currentTarget................................................................................118
16.2.7
El uso del this............................................................................................. 119
16.2.8
Parar la propagacin de un evento.............................................................119
16.2.9
Parar la propagacin hacia otros listeners del mismo elemento y evento. .120
16.3
EVENTOS NO VISUALES............................................................................................. 120
17.
17.1
17.2
17.3
18.

AJAX...................................................................................................122
INTRODUCCIN....................................................................................................... 122
CLASE DE UTILIDAD.................................................................................................122
ESTADOS DE LA PETICIN Y RESPUESTA DEL SERVIDOR....................................................124
MDULOS...........................................................................................126

18

18.1
18.2
18.3
18.4
18.5
18.5.1
18.5.2
18.6
18.7
18.7.1
18.8
19.

INTRODUCCIN....................................................................................................... 126
PARTES DE UN MDULO............................................................................................ 127
IMPORTAR TIPOS...................................................................................................... 127
UN MISMO MDULO EN DISTINTOS ARCHIVOS................................................................128
FUSIONANDO MDULOS CON FUNCIONES Y ENUMS.........................................................128
Funciones.................................................................................................... 129
Enums......................................................................................................... 129
MDULOS EXTERNOS (NODE.JS Y REQUIRE.JS)...............................................................129
TRABAJANDO CON LIBRERAS EXTERNAS.......................................................................130
Archivos de definiciones.............................................................................131
EVITAR QUE UNA CLASE PUEDA SER SUPERCLASE...........................................................131

ANEXO I. ARRAYS................................................................................134

19.1
INTRODUCCIN....................................................................................................... 134
19.2
ATRIBUTOS............................................................................................................ 135
19.2.1
Length........................................................................................................ 135
19.3
MTODOS.............................................................................................................. 135
19.3.1
concat......................................................................................................... 135
19.3.2
every.......................................................................................................... 135
19.3.3
some........................................................................................................... 136
19.3.4
filter............................................................................................................ 136
19.3.5
foreach....................................................................................................... 137
19.3.6
indexOf....................................................................................................... 137
19.3.7
lastIndexOf................................................................................................. 138
19.3.8
join.............................................................................................................. 138
19.3.9
map............................................................................................................ 138
19.3.10
shift............................................................................................................ 138
19.3.11
pop............................................................................................................. 139
19.3.12
push............................................................................................................ 139
19.3.13
unshift......................................................................................................... 139
19.3.14
reduce........................................................................................................ 139
19.3.15
reduceright................................................................................................. 140
19.3.16
reverse....................................................................................................... 141
19.3.17
slice............................................................................................................ 141
19.3.18
sort............................................................................................................. 141
19.3.19
splice.......................................................................................................... 142
19.3.20
toString....................................................................................................... 142
20.

ANEXO II STRINGS...............................................................................144

20.1
ATRIBUTOS............................................................................................................ 144
20.1.1
length......................................................................................................... 144
20.2
MTODOS.............................................................................................................. 144
20.2.1
charAt......................................................................................................... 144
20.2.2
charCodeAt................................................................................................. 144
20.2.3
concat......................................................................................................... 145
20.2.4
indexOf....................................................................................................... 145
20.2.5
lastIndexOf................................................................................................. 145
20.2.6
match......................................................................................................... 145
20.2.7
replace........................................................................................................ 146
20.2.8
search......................................................................................................... 146
20.2.9
slice............................................................................................................ 146
20.2.10
split............................................................................................................. 147
20.2.11
substr.......................................................................................................... 147
20.2.12
substring..................................................................................................... 147
20.2.13
toLowerCase............................................................................................... 147

20

20.2.14
20.2.15
21.

toUpperCase............................................................................................... 147
trim............................................................................................................. 148

ANEXO III. JSON...................................................................................150

21.1
LA
21.1.1
21.1.2

JSON...................................................................................................... 150
De JSON a JS............................................................................................... 150
De JS a JSON............................................................................................... 151

CLASE

22

1. Introduccin
1.1

A quin va dirigido este libro?

Este libro se puede utilizar como texto de aprendizaje sobre el lenguaje de programacin
TypeScript. A su vez sirve como iniciacin para aquellas personas interesadas en la programacin en
general y en el paradigma orientado a objetos en particular. Hace un repaso explicativo sobre las
caractersticas ms importantes de este tipo de lenguajes.
Son recomendables conocimientos de HTML spara entender ciertos temas que cubren
funcionalidades aplicables a la interfaz grfica. Por otro lado, a los que posean experiencia en el
desarrollo con JavaScript les resultar ms fcil la compresin de lo que este libro intenta explicar.

1.2
1.2.1

JavaScript
Historia

JavaScript Javascript (a partir de ahora JS) es un lenguaje de programacin orientado a


objetos mediante prototipos, interpretado, imperativo y funcional. Fue desarrollado por Brendan
Eich, un trabajador de la antigua Netscape. En un principio se denomin LiveScript y se lanz junto
al navegador Netscape Navigator 2.0 en 1995. Posteriormente el nombre cambi a JavaScript por
cuestiones de marketing.
Debido al xito que obtuvo, Microsoft decidi desarrollar el suyo propio al que llam
JScript que en realidad era el mismo lenguaje pero con otro nombre para evitar problemas legales.
En 1997 la ECMA (European Computer Manufacturers Association) desarroll el primer
borrador para estandarizar el lenguaje. Es lo que hoy conocemos como ECMAScript.
Para ms informacin: http://es.wikipedia.org/wiki/JavaScript

1.2.2

mbito de ejecucin

JavaScript se ejecuta en el cliente. Esto quiere decir que la responsabilidad de su


funcionamiento recae sobre nuestra mquina en contraposicin a los lenguajes de servidor (PHP,
Python, etc). Hoy en da JS tambin puede ser ejecutado en el lado del servidor gracias a Node.js.
Normalmente ejecutaremos JS en un navegador web los cuales son capaces de interpretar el
cdigo.

24

1.2.3

Compatibilidad con navegadores

Desgraciadamente para los desarrolladores y usuarios no todos los navegadores interpretan JS


de la misma forma. Aunque se han hecho importantes progresos en los ltimos tiempos, siguen
quedando restos de lo que se ha demostrado ser una chapuza. Navegadores como IE8 y anteriores no
son compatibles con todas las caractersticas del estndar y otras las han adaptado. Es importante que
todo nuestro cdigo sea ejecutable en la mayora de navegadores para tener la mayor cantidad de
usuarios potenciales disponibles.

1.3

TypeScript

TypeScript (a partir de ahora TS) es un lenguaje de programacin de cdigo abierto


desarrollado por Microsoft.
La primera versin se liber en 2012 y a fecha de la edicin del libro la ltima es la 1.1.0.1.
Su estndar es el ECMAScript como lo es tambin de y ActionScript (a partir de ahora AS).
TS es un superconjunto de JS que le proporciona una capa de orientacin a objetos. Por ello no existe
ningn navegador que ejecute TS de forma nativa sino que todo el cdigo es traducido a JS.
Entre sus mejores caractersticas est la compatibilidad con todo el cdigo JS existente.
Podemos usar libreras como jQuery sin problemas pues TS es JS.

1.3.1

Por qu TypeSript?

JS se dise para ser un lenguaje con el que desarrollar pequeas funcionalidades en la web.
Con el paso del tiempo y la llegada de las aplicaciones ricas en Internet (RIA) su uso no slo se ha
extendido, sino que el propio lenguaje se ha visto superado por las circunstancias. Los proyectos son
cada vez ms complejos y necesitan mejores funcionalidades. No es un lenguaje pensado para
grandes aplicaciones por lo que la dificultad para desarrollarlas ha ido en aumento, siendo un
verdadero quebradero de cabeza por sus particularidades como su singular orientacin a objetos
mediante prototipos. Por otro lado no es posible hacer borrn y cuenta nueva y dejar de darle soporte
porque est tan arraigado al mundo web que prcticamente el 99% de las webs actuales no
funcionaran, lo que obligara a hacer nuevos desarrollos. Ante esta tesitura y la cada vez ms fuerte
presin de la comunidad, se intentaron hacer cambios para, de cierta manera, mitigar estos problemas
que ha venido arrastrando. Alternativas como CoffeScript o LiveScript surgieron para este propsito
aunque con un xito moderado. Microsoft ha decidido dar un paso al frente y lanzar su propia
adaptacin, que introduce cambios significativos como el tipado esttico, clases, interfaces, etc, con
una sintaxis similar a Java.

1.3.2

Qu es y no es TypeScript

TS no es nada por s mismo, puesto que su cdigo no se compila ni se interpreta, sino que se
traduce a JS. Una vez traducido, estaramos ante cdigo JS nativo interpretable por cualquier
software que lo permita, como un navegador web.
26

1.3.3

TS es JS

Hay ciertas caractersticas de TS que son traducibles a JS de una forma ms o menos anloga,
como las clases. Hay otras, en cambio, que no, como las interfaces, las cuales no generan cdigo
alguno, es decir, slo existen para comprobaciones en tiempo de compilacin.
TS usa caractersticas de ECMAScript 3, 5 y 6. Algunas de ellas las traduce de forma nativa a
JS, como los getters y setters implcitos de la ECMAScript 5, y con otras no usa las caractersticas
nativas de JS, como los mdulos de la ECMAScript 6. La ECMAScript 6 describe el uso de mdulos
como una caracterstica nueva de JS con una sintaxis determinada. Con TS tambin se pueden usar
mdulos, pero si lo hacemos podemos observar que no traduce el cdigo a la sintaxis del estndar,
sino que ni siquiera hace una traduccin. Eso es as para poder usar lo nuevo de la ECMAScript 6 en
navegadores no compatibles. Pero no todas estn presentes en TS. A su vez posee caractersticas
propias no determinadas en ECMAScript (por el momento) como los genricos.
No todos los navegadores webs con compatibles con todas las funcionalidades de todos los
estndares de ECMAScript, por lo que hay que tener cuidado a la hora escribir nuestro cdigo TS,
pues el uso de ciertas caractersticas lo hara inejecutable en algunos navegadores.
Aqu podemos ver una lista de ECMAScript 5 y 6 y su compatibilidad.
http://kangax.github.io/compat-table/es5/
http://kangax.github.io/compat-table/es6/
Cada archivo .ts se compila en su homlogo .js, incluyendo en l todo el cdigo traducido de
TS a JS. Lo que normalmente conviene hacer es unificar todo el cdigo JS resultante en un solo
archivo .js que posteriormente distribuiremos. Adems, tambin se crean de forma automtica
archivos .maps que relacionan los .ts con los .js. Estos son muy tiles para la depuracin del cdigo
TS.
Realmente TS no se compila ni se interpreta, sino que se traduce. A lo largo del libro se
usarn los trminos relativos a la compilacin para referirse al proceso de traduccin de TS a JS. Si
bien no es el uso correcto s que es el ms amigable para la mayora de los programadores. Microsoft
ha catalogado su herramienta como un transpiler (translator + compiler) que en espaol podra
acuarse como trapilador (traductor + compilador).

1.3.4

Requisitos

El principal requsito para trabajar con TS es Node.js. Si instalamos el IDE Visual Studio 2012
2013 junto con la actualizacin que los hace compatible con TypeScript, Node.js se instalar de
forma automtica. Si no, debemos bajarlo por nosotros mismos desde su web oficial:
http://nodejs.org/
Una vez lo tengamos, podemos escribir en una consola de comandos:
npm install -g typescript
Y TS se instalar de forma automtica. Desde la misma consola podemos comprobar que lo
tenemos con el comando tsc que nos mostrar la versin del compilador y la lista de parmetros que
28

admite. El compilador se aade de forma automtica a la variable PATH del sistema por lo que
podemos invocarlo desde cualquier parte.
Para compilar TS manualmente lo normal sera escribir:
tsc -target ES5 --removeComments --declaration --out app.ts app.js
--target ES5 : Especifica sobre qu estndar queremos compilar. Las opciones son: ES3, ES5
y ES6.
--declaration: genera el archivo de definiciones d.ts Es una herramienta experimental y puede
fallar con el uso de caractersticas avanzadas.
--out app.ts app.js: Esto traducir el archivo app.ts a app.js. y todas las referencias que se
hagan desde app.ts si nuestra aplicacin son varios archivos.
--removeComments : Elimina todos los comentarios.
Normalmente esto no es necesario pero es importante saberlo por si queremos utilizarlo.

30

2. Generalidades
2.1

Sentencias

Una sentencia es una lnea de cdigo escrita en un lenguaje de programacin. En TS se


delimitan con el smbolo ; (punto y coma) como norma general, aunque es opcional. La
recomendacin es escribirlo siempre para no perder la costumbre cuando usemos otros lenguajes
pues en la mayora s es obligatorio. Tambin hace el cdigo ms legible ya que estamos marcando
de forma explcita el final de la sentencia y sabemos exactamente dnde empieza la nueva.

2.2

Sensible a las maysculas

TS es case sentitive. Hay que tener cuidado con esto porque no es lo mismo escribir como
nombre de variable cosa que Cosa o COSA, son totalmente distintas y no tienen relacin alguna. Es
aplicable a funciones, clases, interfaces, etc, es decir, a todo el lenguaje.

2.3

Palabras reservadas

El lenguaje especifica una serie de palabras reservadas que forman parte de su sintaxis. stas
no pueden ser usadas para otra cosa que no sea para lo que se dise y no se permiten nombre de
variables, funciones, etc llamadas de la misma forma:
break, case, catch, continue, default, delete, do, else, finally, for, function, if, in, instanceof,
new, return, switch, this, throw, try, typeof, var, void, while, with, string, number, boolean, Function,
class, interface,public, private, static, protected

2.4

Unicode
Acepta caracteres extraos como la , tildes, y todo el conjunto que permita UTF-8.

2.5

Comentarios

Los comentarios sirven para escribir de forma libre en el cdigo lo que nosotros queramos.
Estn orientados a explicar qu hace y/o por qu lo hace. Son importantes no slo para otras
personas, sino tambin para nosotros mismos.
32

Hay dos tipos de comentarios: en lnea y en bloque. Los comentarios en lnea se construyen
empezando con una doble barra //. Todo lo que escribamos detrs de esa doble barra ser ignorado
por el compilador.
// Esto es un comentario
esto no, y produce un error

El comentario en bloque se empieza con /* y se acaba con */


/* Esto es un comentario
y esto es la continuacin del comentario
anterior en otras lneas */

34

3. Cmo empezar
3.1

Introduccin

Cuando se generan los archivos .js a partir de los .ts, se deben incluir como si de cualquier
otro .js se tratara. Ante una estructura de una pgina web bsica:
<html>
<head>
<title>Yo:TypeScript</title>
</head>
<body>
</body>
</html>

Los archivos .js se incluyen dento de <head></head> de la siguiente forma:


<script type="text/javascript" src="archivo.js"> </script>

Donde src es la ruta hacia el archivo en cuestin.


Una vez lo tenemos, guardamos el archivo con cualquier nombre y con extensin .html. Slo
tenemos que abrirlo con cualquier navegador web para que se ejecute.

index.html
<html>
<head>
<title>Yo:TypeScript</title>
<script type="text/javascript" src="archivo.js"> </script>
</head>
<body>
</body>
</html>

archivo.js
alert(Probando JS);

alert() muestra en una ventana emergente el texto que le proporcionamos.

36

Para slo tener que incluir un archivo .js es preferible compilar y agrupar todo nuestro TS. Es
algo que se puede hacer desde un editor de TS o manualmente desde el compilador con la consola de
comandos. Para ello es necesario que las referencias sean correctas, es decir, que cada archivo .ts
importe los otros .ts que necesite para funcionar. Esto se ver en el captulo de Mdulos.

3.2

Editores

Realmente no es obligatorio un editor de TS pues podemos escribir nuestro cdigo en un


archivo de texto plano y compilarlo a travs de la lnea de comandos. Pero lo que queremos es
facilitarnos las cosas, no complicrnoslas.
Un editor nos ayuda coloreando las palabras reservadas del lenguaje; mostrndonos los
errores sintcticos; autocompletando nuestro cdigo con sugerencias segn vayamos escribiendo,
etc. Adems de compilar TS de forma automtica.
Tenemos que elegir un editor para empezar. Realmente hay pocos disponibles.
Microsoft ofrece uno online en:
http://www.typescriptlang.org/Playground
Pero no sirve para proyectos reales ya que no organiza por archivos ni permite su guardado.
Hay que verlo como un entorno de pruebas rpidas donde podemos, sin necesidad de instalar nada,
ejecutar pequeos trozos de cdigo para observar su comportamiento.
Microsoft tiene su propio IDE para trabajar con TS llamado Visual Studio. Sirven las
versiones de 2012 y 2013 para las que hay que descargar una extensin e instalarla. El gran
incoveniente es que no se encuentra de forma gratuita. Por ello recomiendo una alternativa llamada
TypEcs. Es un plugin de Eclipse, conocido por ser la herramienta de desarrollo para Java ms usada.
Los requisitos para usar TypEcs son tener instalado Java 7, Eclipse Kepler 4.3 y Node.js
0.8.19 o versiones superiores de las anteriores citadas. Se puede descargar desde su web oficial:
http://typecsdev.com/
Una vez cumplidos los requisitos, debemos abrir Eclipse (en la fecha de escritura de este libro
la ltima versin es 4.4 Luna). Una vez hayamos creado el workspace, arrastramos el icono hacia
nuestro Eclipse abierto.

38

De la web http://typecsdev.com/download.html
Aceptamos la licencia y nos pedir permisos para reiniciar Eclipse. Aceptamos y esperamos.
Una vez hecho, creamos nuestro proyecto en File-> New Proyect

Y elegimos Project del desplegable General

Seguidamente pulsamos botn derecho sobre nuestro proyecto y elegimos la opcin


ConfigureAdd TypeScript Support

Ahora crea un nuevo archivo dentro del proyecto con la extensin .ts (app.ts, por ejemplo) y
estamos listos para empezar. Por defecto se compilar nuestro cdigo TS al guardar cualquier cambio
de cualquier archivo que pertenezca al proyecto.
Creamos un archivo con extensin .html y le aadimos la etiqueta script donde el src sea el
archivo .js, en este caso app.js. El cdigo que se deba ejecutar en una web debe hacerse despus de la
carga de la propia pgina pues no ser hasta entonces cuando est todo disponible. Para ello
escribimos en app.ts
window.onload = () =>{
// cdigo
}

Para probar lo que hacemos abrimos el archivo .html creado anteriormente con un navegador
web.

40

Resumidamente, a estas alturas, en nuestro proyecto tendremos:


index.html
app.ts
app.js
El archivo .html incluye en su <head> el archivo app.js. Cada vez que modifiquemos el app.ts
se compilar en app.js.

3.3

Dividir el proyecto

Es evidente que si creamos nuestras clases, interfaces, etc, no lo vamos a hacer en el mismo
.ts, sino que, como es lo normal en la programacin orientada a objetos, cada clase est en un archivo
nico. Por ello, ante esta hipottica estructura:
app.ts
clase.ts
Si en app.ts usamos clase.ts, lo referenciaremos de la forma adecuada en app.ts. A la hora de
compilar TS todo se concentrar en un nico archivo .js. Esto hara que por cada pgina donde
queramos aadir cdigo tendramos compilar el cdigo especfico para esa pgina junto con todas las
utilidades que hayamos creado. No es recomendable porque rompe totalmente con la filosofa de la
reutilizacin. Lo mejor es hacer un proyecto TS donde tengamos todas nuestras creaciones y sea el
resultado de ello lo que usemos en cada pgina.

A modo de ejemplo:
pagina1.html

pagina2.html

Imagina que tenemos dos pginas con esos nombres donde queremos aadir cdigo JS.
Creamos un archivo .ts por cada una (y su .js):
pagina1.html

pagina2.html

pagina1.ts

pagina2.ts

pagina1.js

pagina2.js

Si en cada .ts hemos usado nuestras propias clases, interfaces, etc, lo aadimos a modo de
librera:

42

pagina1.html

pagina2.html

libreria.js

libreria.js

libreria.d.ts

libreria.d.ts

pagina1.ts

pagina2.ts

pagina1.js

pagina2.js

De esta forma usaremos nuestra propia librera como externa, mediante el archivo de
definiciones. As conseguimos reutilizarla en todas las pginas que queramos y separaremos el
cdigo especfico de cada una.

3.4

Libreras externas

Cuando estemos trabajando con libreras externas el procecimiendo es algo distinto. Ya que lo
normal es ofrecer todo nuestro cdigo en un nico archivo .js que es el que realmente se va a usar
finalmente en la web, nosotros podemos ofrecer las nuestras como un proyecto de TS y que sea el
programador que la use el responsable de su compilacin y utilizacin. La otra forma es proveer el
archivo .js junto con un archivo de definiciones. El archivo .js se aade al .html normalmente y es en
nuestro proyecto de TS donde usaremos el d.ts. Si est bien construido todo lo que ah se exponga
tendr su equivalencia en la librera en JS por lo que no habr problemas al ejecutarlo.

44

46

4. Depuracin
4.1

Introduccin
Nota: Las imgenes expuestas en este captulo han sido obtenidas del navegador Chrome de
Google. Otros navegadores tienen un comportamiento similar.

En el desarrollo de nuestra aplicacin se nos hace indispensable el poder ver de una forma
clara qu est haciendo nuestro cdigo mientras se ejecuta. Para ello podemos usar las herramientas
de depuracin de cdigo o debugging. Con ellas observamos el comportamiento de cada sentencia
pudiendo parar su ejecucin en un punto y ejecutarla lnea a lnea con el fin de poder recabar la
informacin necesaria.

4.2

La consola

Una herramienta muy importante es la consola. En ella podemos ver los errores de nuestra
aplicacin as como la lnea de cdigo donde ha fallado. Pulsa F12 para abrirla.

Aqu podemos ver que se ha lanzado una excepcin que no se ha controlado

Intentamos ejecutar un mtodo de un objeto con valor nulo.

Tambin podemos escribir desde nuestro cdigo. Para utilizarla tenemos a nuestra disposicin
el objeto console con una serie de mtodos. Los ms importantes son:

console.log("probando console.log");

48

console.info("probando console.info");

console.error("probando console.error");

4.3

Depurando TS

Realmente no podramos depurar directamente TS pues lo que se ejecuta es su traduccin en


JS. Pero el compilador de TS genera unos archivos .maps que relacionan el cdigo TS con el nativo
en JS. De esta forma, podemos trazar una correspondencia lnea a lnea lo que hace que parezca que
estamos depurando TS de forma directa.
Para activar esta caractersticas en Chrome debemos abrir el navegador y pulsar F12. En la
parte superior derecha de la pestaa que se ha abierto aparece un icono de una sierra dentada como
en la imagen

Pulsamos y nos abrir otra pestaa en la que debemos marcar la opcin Enable JavaScript
source maps

Una vez hecho podemos ver el cdigo TS en la pestaa Sources y eligiendo el archivo .ts que
queramos.
50

4.4

Puntos de ruptura

Llamados break points en ingls. Su utilidad es tan simple como importante. Con ellos
establecemos una lnea en el cdigo donde la ejecucin del programara se parar cuando llegue a ese
punto. Una vez ah tenemos las opciones de seguir con la ejecucin o evaluar expresiones.
Estos se establecen sobre el cdigo en la misma pestaa Sources pulsado sobre la lnea que
queramos. Se ver una etiqueta azul sobre el nmero de lnea.

Si actualizamos la pgina pulsando F5

52

Vemos que la lnea 25, que es donde establecimos el punto de ruptura, se ha coloreado de
azul. En la imagen la ejecucin del programa est parada.
En ese momento tenemos a nuestra disposicin en la parte derecha de esa misma pestaa,
unos botones tiles.

Cdigo

Uso

Contina con la ejecucin hasta el final o hasta que encuentre otro punto de ruptura.

Ejecuta la lnea sobre la que est posicionado y pasa a la siguiente.

Ejecuta el cdigo hasta la siguiente funcin que encuentre.

Ejecuta el cdigo hasta salir de la funcin actual.

Desactiva todos los puntos de ruptura. No los elimina, simplemente los ignora.

Para la ejecucin cuando se lanza una excepcin.

4.5

Evaluador de expresiones

Una vez hayamos parado la ejecucin de nuestro programa, podemos evaluar expresiones en
el watcher seleccionando la variable con el cursor y pulsando botn derecho.

54

Esto aadir el elemento seleccionado a un panel de la parte derecha llamado Watch


Expresions

Si el valor fuera null lo indicara. En este caso se trata de una variable que contiene un nodo
div de id content. Podemos desplegarla para ver con ms detalles de qu se compone.
Resulta increblemente til en situaciones en las que no sabemos qu valor est asignndose a
una variable en la que observamos un comportamiento extrao.
Es posible, tambin, conocer el valor de una expresin comparativa, aritmtica, etc.
Realmente, es posible observar cualquier sentencia.

56

58

5. Variables
5.1

Introduccin

Las variables en TS sirven para lo mismo que en todos los lenguajes de programacin: para
almacenar informacin. Y como su nombre indica pueden variar su contenido durante toda la
ejecucin del programa.
Para crearlas se utiliza la palabra clave var seguido de un nombre identificativo. A esto se le
llama declarar una variable.
var nombre;

Puedes declarar una variable en cualquier momento. Aunque lo ms recomendable es que se


declaren todas antes de empezar la lgica que estemos desarrollando. De esta forma conseguiremos
un cdigo mejor estructurado y legible.

5.2

Nombres de variables

Slo puede estar formado por letras, nmeros y los smbolos $ (dlar) y _ (guin bajo).
Adems el primer carcter no puede ser un nmero.
Ejemplos correctos de variables:
var variable1;
var variable2;
var numeroDeElementos;

Ejemplos errneos:
var var; /* Palabra reservada */
var 1cosa; /* El primer carcter es un nmero */

Se pueden declarar varias en la misma lnea separadas por coma.


var variable1, variable2, variable3;

60

5.3

Inicializacin

Inicializar una variable es asignarle un valor. En TS las variables no se inicializan de forma


automtica como en otros lenguajes de programacin donde, por ejemplo, las de tipo numrica se
inicializan con el valor 0 si no le establecemos un valor explcitamente.
var variable; /* undefined */

Esto es importante porque, por ejemplo, si intentamos hacer operaciones matemticas con
una variable no inicializada, el resultado ser NaN (not a number).
Para inicializarla se usa el operador de asignacin =.
var variable1 = 89;
var variable2 = "esto es una variable";

5.4

mbito de una variable

El mbito o alcance es la zona del programa donde esa variable est disponible para ser
utilizada.
Si declaramos un variable en una funcin, ser local a esa funcin y no se podr usar fuera de
la misma. No existe la declaracin de variables globales dentro de funciones como s ocurre en JS.
Si la variable es un miembro de instancia se podr usar slo dentro de la instancia si es
privada o, si es pblica, desde cualquier parte siempre y cuando estemos dentro del mbito de la
instancia que la contiene. Si es un miembro esttico est disponible slo escribiendo el nombre de la
clase.
El futuro estndar aade un nuevo operador llamado let que permite la declaracin de
variables de mbito de bloque. TS no da soporte a este operador.
var nombre; /* Es accesible desde cualquier parte */
function ambito(): void {
var apellidos; /* Slo es accesible en la funcin */
nombre = "Carlos" /* Podemos acceder a nombre */
}

5.5

Constantes

En contraposicin a las variables estn las constantes, que como su nombre indica, no se les
pueden modificar su valor una vez inicializadas.
TS no da soporte a constantes como tal. Aunque se puede simular en algunas circunstancias.

62

64

6. Tipos
6.1

Variables con tipo


Un tipo identifica lo que almacena una variable. No es lo mismo un nmero que una letra.

Las variables en TS son estticamente tipadas. Esto quiere decir que a la hora declararla
podemos establecer qu tipo de datos contiene. La sintaxis para tipar una variable es la siguiente:
var variable: tipo;

Podemos obviarlo ya que si no lo hacemos se har de forma automtica por inferencia. Mi


recomendacin es que se haga para aproximarnos a la forma de trabajar de muchos otros lenguajes.
Todos los tipos provienen de uno superior llamado Any. El tipo Any se refiere a cualquier
cosa. Si declaramos una variable sin tipar sera lo mismo que hacerlo con Any.
var variable: any;
var variable;

Esto har que podamos asignarle cualquier dato: numrico, caracteres, etc.

6.2

Tipos primitivos y envoltura


Nota: Las especificaciones tcnicas de TS no diferencian explcitamente los primitivos de los
envoltura. Se van a presentar de esta forma ms cercana a Java para una mejor compresin.

Los tipos primitivos son los elementales que nos proporciona un lenguaje de programacin y
cuyos valores son guardados en la posicin de memoria que se le asigna.
A su vez tenemos los tipos envoltura (wrapper en ingls) que no son ms que clases que se
han construido alrededor de estos primitivos para dotarlos de ms funcionalidades.
En TS los tipos primitivos y los envoltura poseen el mismo nombre pero con la diferencia de
que estos ltimos se escriben con la primera letra en maysculas.
Primitivo

Envoltura

Uso

number

Number

Nmeros: enteros y decimales

string

String

Caracteres o cadenas

boolean

Boolean

Slo admiten true o false


66

Si declaramos una variable con un tipo primitivo, no la podemos inicializar con el tipo
envoltura aunque s se puede hacer lo inverso.
var variable1: Boolean = new Boolean(true); // Legal
var variable2: boolean = variable1;// Ilegal boolean/Boolean
var variable3: boolean = true; // Legal
var variable4: Boolean = variable3; // Legal

6.2.1

Inicializacin literal

Consiste es asignarle el valor directamente a una variable sin usar ningn constructor. Tanto
los primitivos como los envoltura pueden ser inicializados de forma literal.
var cadena: string = "Esto es una cadena";
var cadena2: String = "Esto es una cadena";
var numero: number = 2;
var numero2: Number = 2;
var boolean: boolean = true;
var boolean2: Boolean = true;

El por qu de esto se ve mejor con un ejemplo


TS:
var cadena: string = "Esto es una cadena";
var cadena2: String = "Esto es una cadena";

JS:
var cadena = "Esto es una cadena";
var cadena2 = "Esto es una cadena";

Lo que en TS son dos variables de tipos distintos, una primitiva y otra envoltura, en JS son
dos variables sin tipo. El hecho de que no podamos inicializar una variable primitiva usando el
constructor de su equivalente envoltura es una comprobacin del compilador de TS realizada para
mantener la consistencia pero que en JS no ocurre.
TS:
var cadena: string = new String("Cadena"); // Error

JS:
var cadena = new String("Esto es una cadena"); // Correcto

Al tipar la variable con string, en TS ya estamos indicando que debe contener un tipo
primitivo o literal y no va a permitir algo distinto. Como en JS no tipamos la variable, podemos
inicializarla con el primitivo o el envoltura.
68

Cundo usar uno u otro? Vayamos por partes:


Con respecto a number/Number, con el primero se pueden usar los operadores aritmticos y
con el segundo no. Es algo exclusivo de TS ya que en JS es perfectamente vlido por lo que estamos
ante otra comprobacin en tiempo de compilacin. Esto supone un gran inconveniente.
var x: Number = new Number(1);
var y: Number = new Number(1);
var z: Number = x + y; // Error

Para los tipos boolean/Boolean y string/String la eleccin es ms complicada. No existen


diferencias ms all de las incompatibilidades de inicializacin. Pero teniendo en cuenta que es
preferible usar number a Number, son recomendables boolean y string para conseguir coherencia en
el cdigo.
Adems los primitivos tambin nos permiten usar los mtodos tiles que incorporan los tipos
envoltura por lo que no perdemos funcionalidad. Esto es as porque JS hace una conversin de tipos.
Lo hace en una fraccin de segundo sin que nos demos cuenta de ello.
A su vez tambin hace lo inverso, convertir los envoltura a primitivos. Eso es necesario para
poder usar lo operadores aritmticos. Pero aunque JS lo permita, TS lo comprueba en tiempo de
compilacin y lo muestra como un error. Si queremos obtener el valor primitivo de un envoltura
debemos usar el mtodo valueOf():
var envoltura:String = new String("cadena envoltura");
var primitivo = envoltura.valueOf();

Ese mtodo devuelve el tipo Object de TS


var envoltura:String = new String("cadena envoltura");
var primitivo:Object = envoltura.valueOf(); // Correcto
var primitivo2:string = envoltura.valueOf(); // Error

Si queremos hacer clculos con Number lo ms fcil, en realidad, es convertirlos:


var envoltura:Number = new Number(2);
var envoltura2: Number = new Number(2);
var suma:number = +envoltura + +envoltura2;

6.3
6.3.1

Otros tipos
Void

70

Slo sirve para determinar que una funcin no devuelve ningn valor. Tambin se podran
tipar variables con void pero carece de sentido.

6.3.2

Null

No se puede tipar una variable con Null. Slo puede ser el valor de la variable. Cualquier tipo
de variable puede contener el valor null. Representa valor nulo.
var variable: Boolean = null;

6.3.3

Undefined

Representa variables no inicializadas. Tambin podemos asignar el valor undefined a una


variable de cualquier tipo:
var variable: Boolean = undefined;

6.3.4

Enum
Es una forma ms amigable de representar los nmeros.

enum Animales { Perro, Gato, Conejo };


var perro = Animales.Perro;

Perro representara el 0, Gato el 1 y as sucesivamente.

6.3.5

Function
En TS, como en JS, una funcin tambin es un objeto y se puede almacenar como tal.

var funcion: Function;

6.3.6

Array
Los arrays son colecciones de datos. Podemos declarar un array de dos formas:

var array1: Array<tipoDato>;


var array2: tipoDato[];

Son compatibles entre s al 100% y se pueden asignar de forma recproca.


72

tipoDato se refiere al tipo de dato de los objetos que va almacenar el array:


var array1: Array<Number>;
var array2: Array<String>;

Incluso otro array;


var arrayDeArrays: Array<Array<Number>>;

Para inicializarlos tenemos, a su vez, dos formas:


var array1: Array<Number> = new Array<Number>();
var array2: Number[] = [];

En array2 podramos incluso introducir valores separados por comas:


var array2: Number[] = [1, 2, 3, 4, 90];

No hace falta determinar el tamao del array. Este tipo tiene un tamao dinmico que puede ir
creciendo segn las necesidades.

6.3.7

Object
Es el tipo ms bsico de TS. Su uso se ha extendido ya que es la base de JSON.

var objeto1: Object;


var objeto2: {}; // Objeto literal

Y se puede inicializar as:


var objeto: Object = new Object();
var objeto: Object = {};
var objeto: Object = {clave: "valor", clave2: "valor2"};

Es un tipo dinmico. Esto quiere decir que le podemos crear ms claves-valor en tiempo de
ejecucin.
var objeto: Object = {};
objeto["clave1"] = "valor1";

Hay que tener en cuenta las claves slo pueden ser numricas o cadenas de caracteres. El
campo valor, sin embargo, puede ser de cualquier tipo.

6.4

Tipos nombrados y referencia

Podemos crear nuestros propios tipos de datos con clases, interfaces o enumerados. Es una
caracterstica bsica de la programacin orientada a objetos. Se les suele dar el nombre de tipos
referencia aunque en TS obtienen este nombre cuando son usados. Si slo los hemos creado se les
llama tipos nombrados (Named Types). En este grupo entran los tipos envoltura pues son realmente
clases para manejar con ms facilidad los tipos primitivos.
74

6.5

Inferencia de tipos
Inferir, segn la RAE se define como: Sacar una consecuencia o deducir algo de otra cosa.

En este sentido se refiere a la capacidad de deduccin del compilador a la hora de asignar


tipos de forma automtica a variables no tipadas explcitamente, segn ciertas circunstancias.

6.5.1

Inferencia bsica
Es la que ocurre cuando se nos olvida tipar una variable que hemos inicializado.

var cadena = "inferencia";

El compilador tipa de forma automtica la variable cadena porque sabe que su contenido es
un string.
Si inicializamos de forma literal, la inferencia del tipo ser de primitivos. Si inicializamos con
el constructor de las clases de envoltura, la inferencia ser del tipo de la envoltura.
var x = 3; // Tipado con number
var y = new Number(3); // Tipado con Number

6.5.2

Expresiones tipadas por el contexto


El tipado contextual es una caracterstica de TS que nos ahorra cierto trabajo.
Si tenemos una funcin:

var func: (x: number) => string = (x) => "func";

En la inicializacin de la funcin no hemos especificado el tipo del parmetro pero no hara


falta porque TS, gracias al tipado contextual, sabe que es un number.
Esto tambin ocurre en el sentido contrario:
var func = (x: number) => "func";

Ahora no hemos especificado nada a la hora de definir la funcin pero, de nuevo, TS sabe
reconstruir la definicin a partir de la inicializacin.
Si no lo hacemos ni en un lado ni en otro, es imposible para TS saber de qu se trata por lo
que lo tipa con Any.
var func = (x) => "func";

76

6.6

El mejor tipo comn


Hay situaciones en las no hemos tipado un array y lo hemos rellenado de valores de distinto

tipo:
var x = ["uno", null, "dos"];

El compilador, para tipar por inferencia, elige la mejor opcin. En este caso hay dos
elecciones posibles: string y Null. Como Null es compatible con cualquier tipo, elige tipar el array
con string. En consecuencia x sera un string[] (array de strings).

6.6.1

Any como tipo general


Si introducimos una variable any en el array, el mejor tipo comn ser any[]

var x: any;
var array = [x, "Carlos", true]; // Resultado any[]

6.6.2

{}

Si introducimos un objeto {} en el array o un Object (new Object() ), el mejor tipo comn


ser el objeto vaco siempre y cuando no haya ninguna variable Any. En ese caso ser Any.
var
var
var
var

x: any;
array = ["Carlos", {}] // {}[]
array2 = [x, "Carlos", {}] // any[]
array3 = [x, "Carlos", new Object()] // any[]

6.6.3

Entre primitivos

No va a encontrar un mejor tipo comn ms all de {}[] si en el array introducimos dos o


ms de estos tipos: string, number, boolean o Array
var array = ["Carlos", 24] // Resultado {}[]

6.6.4

Entre primitivos y envolturas

Si introducimos un tipo primitivo y otro envoltura relacionados (number/Number) el mejor


tipo comn ser el de la envoltura.
var array = [3, new Number(1)] // Resultado: Number[]

6.6.5

Entre tipos referencia


78

Si rellenamos el array con instancias de clases o interfaces el mejor tipo comn ser aqul
que sea compatible con todos los dems. En el caso de que no exista, el resultado ser {}. Aunque
las clases instanciadas sean subclases de otra comn, el algoritmo debe elegir entre los tipos
explcitamente introducidos.
class A { }
class B { }
var array = [new A(), new B()] // A[]

Si existe ms de un mejor tipo comn posible, escoge el primero que encuentra. En este caso
A.
class A { }
class B extends A { }
class C extends A { }
var array = [new B(), new C()]; // B[]

Aunque B y C sean subclases de A, al no estar A explcitamente en el array, no puede


escogerla como mejor tipo comn.

6.7

typeof

Este operador es muy til pues nos informa del tipo de dato de una variable. El resultado que
nos devuelve es un string.
var cadena: string = "probando typeof"; // string

Hay que tener cuidado con esto:


var cadena: String = new String("probando typeof");

Si hacemos typeof cadena, el resultado ser object. Por qu? Pues porque realmente es un
object ya que String es una clase de envoltura. La nica forma de poder saber el tipo de dato
especfico es inicializando las variables literalmente. No importa si tipas la variable con string o
String, lo importante es lo que le asignes.

Devolver string:
var cadena1: String = "probando typeof";
var cadena2: string = "probando typeof";

Devolver object
var cadena: String = new String("probando typeof");

Esto es aplicable no slo a String, sino a todos los dems como Number, Boolean
80

Con este operador tambin podemos tipar una variable con el tipo de otra. Es lo que se
conoce en TS como tipos consulta.
var x: number = 5;
var z: typeof x = 2;

Incluso lo podemos hacer por inferencia.


var x = 5;
var z: typeof x = 2;

Aunque no hayamos especificado el tipo de x, el intrprete sabe que es del tipo number por lo
que podemos hacer que z sea de ese tipo.

6.8

El uso de la memoria

Los valores primitivos son alojados en una zona de la memoria directamente. Los tipos
referencia, sin embargo, reservan un espacio de memoria cuya direccin se almacena en esa variable.
En ese espacio se guardan otras direcciones de memoria que apuntan a los atributos.
Hay que tener en cuenta que el propio lenguaje puede ofrecer tipos de datos referencia como,
por ejemplo, los envoltura: String, Number o Boolean.
Esto tiene consecuencias como la comparacin de objetos o el paso de los mismos como
argumentos de funciones.

82

84

7. Operadores
7.1

Operadores unarios
Los operadores unarios son aqullos que slo necesitan un operando para poder ser usados.

7.1.1

Operadores ++ y -Slo para Any, number y enum.

Son los llamados incremento (++) y decremento (--). Sirven para sumar o restar una unidad a
un nmero. A su vez, dependiendo de dnde lo escribamos, pueden ser preincremento/predecremento
o postincremento/postdecremento.
var num: number = 0;

Y le hacemos un postincremento:
num++ // 1

Lo mismo ocurrira si hacemos:


++num // 1

La diferencia entre el pre y post, es el orden. En pre, primero se ejecuta el operador.


Si hacemos esto:
var num: number = 1;
var num2: number = --num;

Cul ser el valor de num2? 0. Por qu es 0? Porque primero se ejecuta el operador, es


decir, se reduce en 1 la variable num y luego se asigna a num2.
Pero si hacemos esto:
var num: number = 1;
var num2: number = num--;

El valor de num2 ser 1. Pues primero se ha asignado el valor de num a num2 y despus se la
ha restado uno.
Si se usa con Any slo tiene sentido si almacena un nmero o una cadena que representa un
nmero.
86

var ejemplo: any = 10;


ejemplo++; // 11
var ejemplo: any = "10";
ejemplo++; // 11. Ha convertido la cadena en un nmero
var ejemplo: any = "a";
ejemplo++; // NaN. No puede sumarle 1 a la letra a

7.1.2

Operadores +,
Slo sirven para number, Any y enum.
Convierten un valor del tipo Any a number.

var num: number = +"1"; // string 1 a number 1


var num2: number = -"1"; // string 1 a number -1

El operador - tambin puede usarse con number para negativizar.


var num: number = -1;

7.1.3

Operador ~

Es el complemento a uno. Cambia todos los bits 0 a 1 y todos los bits 1 a 0. En la prtica
convierte un nmero en su inverso y le resta 1.
var x: number = ~10; // -11
var y: number = ~-10; // 9
var z: number = ~~10; /* 10. El complemento del complemento es el nmero
original */

7.1.4

Operador !
Sirve para negar una expresin o un tipo de datos boolean o Boolean.
Si tenemos esto:

var verdadero: boolean = true; // true


var falso: boolean = !verdadero; // false

Si negamos true, lo convertiremos en false. Si negamos false lo convertiremos en true.


Tambin puede ser usado para convertir a boolean.
var verdadero: boolean = !"true";

Estamos convirtiendo el string true a boolean false. Si queremos convertirlo a boolean true,
basta con negar dos veces.
88

var falso: boolean = !!"true";

7.1.5

Operador delete
Borra propiedades de objetos o elementos de un array.

Si se borra la posicin de un array, ste no se redimensiona, sino que convierte esa posicin
en undefined.
Devuelve true o false dependiento de si ha podido eliminar o no el elemento.
var x: number = 1;
var obj: Object = { x: 1 };
delete x; /* false. Las variables no se pueden borrar */
delete obj["x"] // true

7.1.6

Operador void
Evala una expression cualquiera y siempre devuelve undefined.

Suele usarse en el href de los enlaces anchor para realizar alguna accin evitando que se
comporte por defecto.
<a href="javascript:void(document.body.style.backgroundColor='green');">Click here
for green background</a>

7.2

Operadores binarios
Los operadores binarios son aqullos que necesitan dos operandos para poder ser usados.

7.2.1

Operador de asignacin

Es el = (igual). Ya vimos que se usaba para inicializar las variables. La regla que sigue es que
todo lo que hay a la derecha del = se asigna a lo que hay a la izquierda y no al revs.
No podemos hacer esto:
1 = var num: number;

7.2.2

Operadores lgicos

Se usan para evaluar expresiones dando como resultado true o false. Son muy tiles para las
estructuras de control de flujo.

90

Son operadores llamados perezosos porque no siguen evaluando en cuanto el resultado de una
expresin o conjunto de ellas es suficiente para determinar toda la condicin.

7.2.2.1

false en TS
0, "" (cadena vaca), null y undefined

7.2.2.2 Operador AND


Se representa: &&
Ser true si, y slo si, todas las expresiones son true.
expresin1

expresin2

expresin1 && expresin2

true

true

true

true

false

false

false

false

false

false

false

false

Si alguno de los dos se evala como false, el resultado ser false. Una expresin puede ser
una variable o una expresin compleja. Se pueden hacer todo lo extensas que se desee
&& && ... && &&
Incluso se puede establecer prioridades con parntesis:
expresion1 && (expresin2 && expresion3)
expresion2 y expresion3 actan como una a la hora de evaluarse de forma conjunta con
expresion1
Tambin puede usarse para una asignacin condicional. Si el primer operando se evala como
true, se asignar el valor del segundo operando. Si se evala como false, se asignar el valor del
primero. La variable siempre quedar tipada con el tipo de dato del segundo operando.
var and = false && "cadena"; // false

Es muy til cuando lo usamos con instancias que no sabemos si son null/undefined o no.
var persona: Persona = null;
var nombre = persona && persona.nombre; // undefined

Como persona no es una instancia de Persona, no tiene acceso a sus atributos, por lo que
persona.nombre fallar. De esta forma nos aseguramos que esto no ocurre porque si persona es null (

92

y null es false), se asignar a nombre el valor del primer operando sin evaluar el segundo. Si persona
no fuera null evaluara persona.nombre y se lo asignara a nombre.

7.2.2.3 Operador OR
Se representa ||
Ser true si alguno de los operandos es true.
expresin1

expresin2

expresin1 || expresin2

true

true

tue

true

false

true

false

false

true

false

false

false

Al igual que con AND, se pueden hacer todo lo largas que se quiera.
Tambin puede usarse para una asignacin condicional.
var or = false || 4; // 4
var or = 10 || "or"; // 10

Si el primer operando se evala como true, se asignar a la variable. Si se evala como false,
se asignar el segundo operando sea cual sea su valor. La variable quedar tipada como el mejor tipo
comn entre ambos operadores.
Es muy til para inicializar variables que no sabes si ya lo estn.
var nombre: string;
nombre = nombre || "Carlos";

Evala nombre. Al ser null, y null ser false, asigna el valor del segundo operando a la
variable. Si nombre ya estuviera inicializado, lo evaluara como true y le asignara el valor del
primer operando a la variable.

7.2.3

Operadores aritmticos

Estos operadores son exclusivos para number, Any y enum. No se pueden usar con Number.
El resultado siempre ser un nmero.

94

7.2.3.1 Operadores + y Son los usados para sumar y restar nmeros respectivamente.
var x: number = 2;
var y: number = 2;
var suma: number = x + y; // 4
var resta: number = x - y; // 0

7.2.3.2 Operadores * y /
Son los usados para multiplicar y dividir nmeros respectivamente.
var x: number = 2;
var y: number = 2;
var multiplicacion: number = x * y; // 4
var division: number = x / y; // 1

7.2.3.3 Operador %
Obtiene el resto de una divisin.
var x: number = 5;
var y: number = 2;
var resto: number = x % y; // 1

Todo ellos tienen la forma corta de este tipo:


var x: number = 1;
x *= 3; // Equivalente a x = x * 3;

7.2.4

Operadores de bits

7.2.4.1 Operadores lgicos bit a bit


Esto operadores realizan la operacin bit a bit. Eso signfica que convierten el nmero a
binario y van comparando uno a uno los bits de la misma posicin. Dependiendo del operador usado,
el resultado ser 0 1, lo que conformar un nuevo nmero.
96

operador

uso

&

Realiza la operacin AND bit a bit.

Realiza la operacin OR bit a bit.

Realiza la operacin XOR bit a bit

var x: number = 15;


// x: 01111
var y: number = 20;
// y: 10100
var z: number = x & y; // z: 00100 Es el nmero 4
var x: number = 15;
// x: 01111
var y: number = 20;
// y: 10100
var z: number = x | y; // z: 11111 Es el nmero 31
var x: number = 15;
// x: 01111
var y: number = 20;
// y: 10100
var z: number = x ^ y; // z: 11011 Es el nmero 27

7.2.4.2 Operadores << y >>


Son los usados para desplazamiento de bits. Si desplazamos un bit a la izquierda el resultado
es la multiplicacin por 2 del nmero. Si desplazamos un bit a la derecha, el resultado es la divisin
entre 2 del nmero. Se pueden hacer los desplazamientos que queramos y se van concatenando.
var x: number = 10;
x << 3 // 80. 10*2*2*2
x >> 1 // 5. 10/2

7.2.5

Operadores relacionales

Comparan datos. Es obligatorio que los dos operandos sean del mismo tipo. Si uno de los dos
es any el otro puede ser de cualquiera tipo. El resultado siempre ser un boolean: true o false.

7.2.5.1 Operadores <, >, <=, >=,


Se usan para comprobar si un dato es mayor, menor o igual que otro.
var x: number = 5;
var y: number = 2;
x
x
x
x

> y; // true
< y; // false
>= y; // true
<= y; // false

98

Se puede usar tambin con string. Todos los caracteres tienen un cdigo numrico que los
identifica. La comparacin se hara en base a l.
"a" > "A"; // true
"b" > "A"; // true

Como puedes ver, b es mayor a A porque el cdigo ASCII de la letra b minscula es


mayor que el cdigo ASCII de la letra A mayscula. Las letras maysculas tienen un cdigo menor a
las minsculas.
Ms informacin sobre ASCII:
http://es.wikipedia.org/wiki/ASCII

7.2.5.2 Operadores == y !=
Se usan para comprobar si un dato es igual o distinto a otro, respectivamente. El resultado
siempre ser un boolean. Estos operadores slo comprueban el valor y no el tipo del dato pues hace
una conversin de tipos si puede.
var x: number = 5;
var y: number = 5;
x == y; // true
x != y; // false
null == undefined; // true

Se pueden comparar prmitivos y envoltura indistintamente.


var x: Number = new Number(5);
var y: number = 4;
var a:string = "A";
var b:String = new String("B");
x == y; // false
a != b; // true

7.2.5.3 Operadores === y !==


Se usan para comprobar si un dato es igual o distinto a otro respectivamente. El resultado
siempre ser un boolean. Estos operadores s comprueban el tipo de datos adems del valor. No hace
conversin de tipos.
var x: Number = new Number(5);
var y: number = 5;
var a:string = "A";
var b:String = new String("B");

100

x === y; // false
a === b; // false

Esta vez no slo comprueba el valor, sino tambin el tipo sin hacer conversion. Como
number y Number no son el mismo tipo ni tampoco string y String, el resultado de las
comprobaciones del ejemplo son false.
Cmo se evaluara una comprobacin de igualdad entre dos String (envoltura) cuyas
cadenas fueran iguales?
var a = new String("cadena");
var b = new String("cadena");
a === b; // false
a == b; // false

La evaluacin es false porque est comparando envolturas, que son objetos referencia. Y esta
comparacin se hace en base a la direccin de memoria. Si las direcciones son iguales, los objetos
tambin lo son. En el ejemplo hemos instanciado dos veces la clase String por lo que tenemos dos
objetos con direcciones distintas.
Para que la igualdad se pueda evaluar como true:
var a = new String("cadena");
var b:String = a;
a === b; // true
a == b; // true

En este caso a la variable b se le est asignando a, es decir, b contiene la misma direccin que
a por lo que los dos apuntan al mismo espacio de memoria y son, en realidad, el mismo objeto.
Es aplicable a cualquier tipo referencia, ya sea estndar del lenguaje o creado por nosotros.
Esto implica que dos variables de tipos envoltura relacionados pueden ser distintos a ojos del
operador pero iguales en valor. Una de las opciones para poder hacer la comparacin es usar el
mtodo toString().
var a = new String("cadena");
var b = new String("cadena");
a.toString() == b.toString() // true

7.2.6

Operador + de concatenacin
Requiere que al menos uno de los operandos sea Any o string.

Si los dos operandos son number, el resultado ser number. En este caso estara actuando
como
operador
suma.
102

Si al menos uno de ellos es string el resultado ser string porque los concatena, es decir, los une. En
este caso estara actuando como operador de concatenacin.
var cadena1 = "Hola, ";
var cadena2 = "Mundo";
cadena1 + cadena2; // "Hola, Mundo"
var cadena1 = "Somos";
var numero = 2;
cadena1 + numero; // "Somos 2"

Podemos convertir un tipo number, Any o enum a string concatenndole la cadena vaca.
var x: any = 10;
x+""; // "10"

7.2.7

Operador in

Busca el valor del operando de la izquierda, que debe ser Any, string o number, en el
operando de la derecha, que debe ser Any, object o array devolviendo true si lo encuentra y false en
caso contrario.
No busca valor de los atributos, sino el nombre de los mismos.
var animales = ["Perro", "Gato", "Conejo"];
"Perro" in animales; /* False. Perro es un valor del ncide 0 del array */
1 in animales; /* true. El array contiene 3 valores con lo cual existe el ndice 1
*/
var obj = {animal:"Perro"}
"Perro" in obj; /* False. Perro es un valor del ncide animal */
"animal" in obj; // True. Animal es un ndice

7.2.8

Operador condicional terciario

Sirve para asignar a una variable un valor dependiendo de una cierta condicin. Es un un caso
especfico de if que resulta muy prctico.
var x:number = 10;
var z:number = x == 10 ? 1 : 100; // 1

La variable x vale 10. A la variable z se le asigna un valor dependiendo de una condicin que
en este caso comprueba si la variable x vale 10. Si es cierto, a z se le asigna 1, en caso contrario se le
asigna 100;
Para hacer un simil con ||, recordemos:

104

var nombre: string;


nombre = nombre || "Carlos";

Podramos, tambin, expresarlo de la siguiente forma:


nombre = nombre ? nombre: "Jos Carlos";

A nombre se le asigna un valor dependiendo de la condicin dada. En este caso comprueba si


nombre es true o false (nombre es null que como ya sabemos se evala como false). Si fuera true, a
nombre se le asignara el valor que ya tiene. Como es false se le asigna Carlos.

106

108

8. Control del flujo


8.1

Introduccin

La idea bsica de la programacin es la automatizacin de procesos en los que un humano


debera hacerlos de forma manual cada vez que quisiera obtener resultados. Por ello es
imprescindible poder controlar la ejecucin del programa tomando decisiones sobre qu debera o no
ejecutar dependiendo de la situacin. Por otra parte, no basta con bifurcar los caminos, sino que
debemos tener algn mecanismo para repetir sentencias de forma que no nos obligue a escribir un
nmero X de veces situaciones anlogas.

8.2
8.2.1

Selectivas
if

Sirve para tomar decisiones bajo alguna condicin. Aqu es donde resultan imprescindibles
los operadores lgicos.
if (/*condicin*/) {
// Cdigo
}
var x = 5;
if (x == 5) { /* Se ejecuta si x es igual a 5 */
// Cdigo
}

Se puede usar el bloque else que engloba todo lo que no lo hace la condicin original.
if(x == 5) {
/* Se ejecuta si x es igual a 5 */
}
else{
/* Si no es igual a 5 entra aqu */
}

Adems se puede usar el bloque else if para determinar ms casos.


if(x == 5){ // Se ejecuta si x es igual a 5
// Cdigo
}else if (x == 6) {
// Si es igual a 6
} else {

110

// Si no es igual ni a 5 ni a 6
}

En la condicin puedes usar todos los operadores de comparacin que quieras junto con
operadores lgicos.
var x: number = 5;
var y: number = 10;
if (x == 5 && y == 10) {
/* Se ejecuta si x es igual a 5 y, adems, y es igual a 10 */
}

8.2.2

switch

Es una estructura de eleccin que puede sustituirse por if-else pero que en ciertas
circustancias resulta ms prctico.
var x: number = 1;
switch (x) {
case 0:
// Hacer algo si x vale 0
break;
case 2:
// Hacer algo si x vale 2
break;
default:
/* Hacer algo en el caso de que no sea ninguno de los anteriores */
break;
}

Es importante el break porque sin l tambin se ejecutara el siguiente caso aunque no lo


cumpliera.
Tambin puedes agrupar casos para un mismo cdigo.
var x: number = 1;
switch (x) {
case 0:
case 1:
case 2:
// Hacer algo si x vale 0, 1 2
break;
default:
/* Hacer algo en el caso de que no sea ninguno de los
anteriores */
break;
}

112

8.3

Iterativas

Un bucle es una repeticin limitada o no (los bucles infinitos no son buena idea) de un bloque
de cdigo. Si, por ejemplo, queremos mostrar por pantalla los 100 primeros nmeros y no usramos
bucles, tendramos que escribirlos todos a mano. Absurdo, no crees?

8.3.1

while
El bucle while se ejecuta mientras la condicin sea true.

var x: number = 0;
while (x < 10) {
x++; // x va incrementndose en 1 en cada iteracin
}

Cuando llegue a 10, se evaluar como false y el bucle dejar de ejecutarse.

8.3.2

do-while

Es similar a while pero mientras el while no se ejecuta si no se cumple la condicin, el do


while se itera al menos una vez, y las siguientes si cumple la condicin.
var x: number = 0;
do {
x++;// Se ejecuta una vez al menos
} while (x < 10);

Se ejecutar mientras x sea mejor de 10. En cuanto sea 10, se saldr del bucle.

8.3.3

for

Es un bucle un tanto distinto a while pues en su definicin se declara una variable numrica
que sirve de ndice.
for (declaracin; condicin; actualizacin) {
// Cdigo
}
var nombres: Array<string> = ["Jos", "Carlos", "Lama"]
for (var i: number = 0; i < nombres.length - 1; i++) {
}

console.log(nombres[i]);

Se va iterando sobre el array de forma que el ndice i va aumentando en uno cada iteracin y
as vamos obteniendo los valores de las distintas posiciones del array.
No est restringido a una sola declaracin, condicin y actualizacin. Ni siquiera esta ltima
debe ser una sucesin creciente.
114

Podemos declarar ms de una variable y hacer que la condicin sea ms compleja con
operadores lgicos. Adems en la actualizacin podemos usar cualquier operador matemtico. La
nica restriccin es que el ndice ha de ser numrico entero.

8.3.4

for-in

Es similar al for pero no se declara un ndice numrico y recorre la estructura de principio a


fin, sin condiciones.
var nombres: Array<string> = ["Carlos", "Jos", "Lama"];
for (var indice in nombres) {
console.log(nombres[indice]);
}

Va volcando el ndice de nombres de la variable indice. La ventaja es que no importa de qu


tipo sea el ndice: numrico, cadena de caracteres, etc.

8.4
8.4.1

Sentencias tiles para los bucles


break
Corta la ejecucin del mismo.

var nombres: Array<string> = ["Carlos", "Jos", "Lama"];


for (var indice in nombres) {
if (nombres[indice] == "Jos" ){
break;
}
// Ms cdigo. No se ejecuta.
}

Cuando encuentra el valor Jos en el array nombres, ejecuta el break y no sigue iterando.

8.4.2

continue
Ejecuta la siguiente iteracin sin haber acabado la actual.
116

var nombres: Array<string> = ["Carlos", "Jos", "Lama"];


for (var index in nombres) {
if ( nombres[index] == "Jos" ){
continue;
}
// Ms cdigo No se ejecuta.
}

Si encuentra el valor Jos en el array nombres itera el siguiente sin ejecutar el cdigo que
quedaba.

118

120

9. Funciones
9.1

Introduccin

Las funciones no son ms que sentencias agrupadas para solucionar un problema en


particular. De esta forma la invocamos cuando sea necesario evitando la repeticin de cdigo.
TS hereda la forma en la que trabajan las funciones en JS pero aadindole extras
sustanciales.

9.2

Declaracin

Una funcin se divide en dos partes: cabecera y cuerpo. La cabecera define a la funcin
mediante un nombre, una lista de parmetros (opcional) separados por coma y una salida (puede ser
la salida vaca).
Para declarar una funcin utiliza la palabra reservada function seguida de la cabecera y del
cuerpo, el cual est encerrado entre llaves.
function nombreDeLaFuncion():void
/* esta es la cabecera de la funcin. El nombre debe seguir la nomenclatura
de nombre de una variable */
{/* Y este el cuerpo */}

9.3

Parmetros de una funcin

*Nota: comnmente a los parmetros se les llama tambin argumentos, separando los
parmetros/argumentos formales y los parmetros/argumentos actuales. Los primeros son
propiedades intrnsecas que estn definidas en la cabecera de la funcin. Los segundos son los
valores que se le pasan a esa funcin en la invocacin de la misma. Para facilitar las cosas, a partir
de ahora llamaremos simplemente parmetros para referirnos a los formales y argumentos para
referirnos a los actuales.

Los parmetros se definen de la siguien forma:


function nombreDeLaFuncion(*/listaParametros*/):void

122

listaParametros representa una lista de parmetros separados por coma. Los parmetros son
valores que la funcin acepta como entrada. Esto resulta muy til para construir funciones ms
reutilizables que nos ahorren tiempo y trabajo. Los parmetros se declaran exactamente igual que las
variables pero sin la palabra reservar var.
function funcion (x: number, z: number): void { }

Hemos declarado dos parmetros llamados x y z respectivamente del tipo number. Esto quiere
decir que para poder utilizar esa funcin debemos pasarle como argumentos dos nmeros o algn
tipo de dato compatible con number.

9.3.1

Parmetros opcionales y por defecto

En TS podemos hacer que un parmetro de una funcin sea opcional, e incluso asignarle un
valor por defecto. Para hacer que sea opcional escribimos el smbolo ? justo despus del nombre del
parmetro.
function sumar(x: number, z?: number): number {return x * y;}

Si llamamos a la funcin slo con un argumento:


sumar(10);

E inspeccionamos el valor de z, nos dara undefined, pues no lo hemos especificado.


Pero si llamamos a la funcin pasndole dos argumentos:
sumar(10,20);

El valor de x sera 10 y el de z sera 20.


Tambin podemos asignar un valor por defecto.
function sumar(x: number, z?: number = 20): number {
return x * z;
}

De esta forma, aunque llamemos a la funcin con slo un argumento, la z valdr 20 y no


undefined.
Los parmetros opciones e inicializados no pueden colocarse delante de uno no opcional ni
inicializado.
function sumar(x?: number, z: number): void { } // Error
function sumar(x: number = 20, z: number): void { } // Error

9.3.2

Ms parmetros

Existe una forma de aceptar una lista infinita de argumentos por parmetro. En TS se llama
el resto de parmetros.
124

Es bastante sencillo:
function mas(x: number, ...masParametros): number{
}

return x;

Como puedes observar, basta con definir un parmetro ms anteponiendo (tres puntos
suspensivos) a su nombre. Ser del tipo Array de Any. Podemos tiparlo para que sea un Array de otra
cosa pero siempre un Array.
function mas(...masP: number[]):void {}

Este parmetro especial no puede ser opcional ni puede estar inicializado.


function mas(...masP?: number[]): void { }; // Error
function mas(... masP: number[]=[]): void { }; // Error

Para usarlo lo hacemos como si de un array cualquiera se tratara.


function sumar(...masP: number[]): number
{
var total: number = 0;
for (var i: number = 0; i < masP.length; i++) {
total += masP[i];
}
return total;
}
var suma: number = sumar(3, 56, 89, 12, 56); // 216

La funcin suma todos los nmeros del array introducido como argumento y devuelve el
resultado.

9.3.3

Parmetros por valor o por referencia

A la hora de pasar argumentos a una funcin, se puede hacer de dos formas: por valor o por
referencia. Esto no lo decidimos nosotros (no en TS. Existen otros lenguajes donde s podemos
elegir).

9.3.3.1 Por valor


El paso por valor es el ms sencillo. Cuando invocamos una funcin e introducimos un valor
como argumento, se realiza una copia del valor hacia el parmetro de la funcin. Que sea una copia
quiere decir que el valor pasado y el parmetro ya no tienen relacin en la memoria en el momento
de la ejecucin.
var x: number = 5;
function valor(y: number): void {
y++; // 6
}
x; // 5

126

Hemos creado una variable de tipo number con un valor inicializado de 5. Hemos invocado la
funcin pasando esta variable como argumento. En ese momento se ha creado una copia de la
variable x de fuera de la funcin hacia la variable y de dentro de la funcin. Si modificamos la
variable y (en este caso hemos sumado uno) vemos como la x se mantiene intacta.

9.3.3.2 Por referencia


En contraposicin al paso por valor existe el paso por referencia. En ste no se hace una copia
del valor de la variable hacia el parmetro de la funcin, sino que lo que se le pasa es la referencia de
la direccin de memoria.
Cuando se crea una variable se reserva un espacio de memoria donde almacenarla. Ese
espacio de memoria tiene una direccin que maneja internamente la mquina virtual. Al hacer un
paso por referencia lo que se le proporciona es esta direccin de memoria a otra variable. Dos
variables, a priori distintas, que posean la misma direccin estn apuntando al mismo lugar de la
memoria por lo que en realidad son la misma variable.

var x: Array<number> = [0, 0];


x[0]; // 0
function referencia(y: Array<number>): void {
y[0] = 1; // 1
}
referencia(x);
x[0]; // 1

Tenemos un Array de number con dos posiciones, ambas con valor 0.


Le pasamos el array a la funcin y la posicin 0 que vale 0, la cambiamos a 1.
Al acabar la ejecucin de la funcin y mostrar el contenido de la posicin 0 del array, vemos que lo
cambiado en la funcin persiste, al contrario de lo que pasaba con el ejemplo del paso por valor.
Como hemos dicho lo que ha ocurrido es que a la funcin se le ha pasado la direccin de
memoria del array. Gracias a esto, al usar la variable lo que estamos haciendo es trabajar
directamente sobre el array original.

9.3.3.3 Paso por copia referencial


El paso por referencial no es cierto al 100%. Lo que realmente hace es un paso por copia
referencial. Esto es que no pasa la direccin de memoria original, sino una copia de la misma.
En el da a da no es muy comn pensar en esto pues casi no afecta a nuestros diseos pero
por ejemplo, no podramos hacer esto:
var x: Array<number> = [0, 0];
x[0]; // Muestra 0
function copiaRef(y: Array<number>): void {
y = [1, 1];

128

y[0]; // 1
}
copiaRef(x);
x[0]; // 0

Es igual que el ejemplo del paso por referencia pero con la diferencia de que no cambiamos la
posicin 0 del array y, sino que lo volvemos a inicializar pero con el valor 1 en cada posicin. Al
acabar la ejecucin de la funcin y mostrar la posicin 0 de x, segn lo que hemos aprendido debera
ser 1. Pues no, es 0. Por qu? Porque, como se ha explicado anteriormente, no se le ha pasado la
direccin de memoria original, sino una copia.

9.4

Valores de retorno

Las funciones pueden devolver un valor si as lo precisamos. Para ello se debe especificar en
la cabecera de la funcin el tipo de dato que queremos devolver: number, string, Array Si la
funcin no va a devolver nada, hay que especificarlo con la palabra reservada void.
function devuelve (x: number, y: number): number
{ return 4} // Devuelve un nmero
function noDevuelve(x: number, y: number): void
{ /* No devuelve nada */}

Para ello se hace con la palabra reservada return. Si se especifica un tipo de retorno, es
obligatoria, mostrando un error si no se hace. Una vez ha devuelto algn valor, se corta la ejecucin
de la funcin por lo que si hay algo posterior no se tendr en cuenta.
function conReturn(x: number, y: number): number
{
return x * y;
x = y + 2; /* No se ejecuta pues el flujo de la funcin ha acabado debido
al return*/
}

9.5

Invocando funciones

La forma de usarlas es sencilla. Para invocarlas basta con escribir su nombre y la lista de
argumentos que coincida con sus parmetros, si los hay.
function sumar(x: number, y: number): number {return x + y;}

Para usarla basta con:


sumar(5, 5);

Si la funcin devuelve void, es decir, vaco, no tiene sentido asignrselo a una variable. Pero
si devuelve un tipo distinto a void, s que puede llegar a merecer la pena.
130

var suma: number = sumar(5, 5); // 10

El valor de suma ser de 10 que es el valor devuelto por la funcin.

9.6

Sobrecarga

La sobrecarga de funciones consiste en declarar dos o ms funciones con el mismo nombre


pero con distinto nmero de parmetros. En TS no existe la sobrecarga de funciones como tal.
No podemos hacer esto:
function sobreCarga(x: number): number {
return x;
}
function sobreCarga(x: number, z:number): number {
return x * z;
}

Pero lo que s existe es una misma implementacin para varias declaraciones de una funcin
con el mismo nombre si tenemos una definicin que englobe a todas las dems.
function sobreC(x: number): number
function sobreC(x: number, z:number): number
function sobreC(x: number, z?: number): number {
return x;
}

El gran inconveniente es que tenemos que controlar los valores en el cuerpo de la funcin. No
podemos operar con z si no sabemos si realmente tiene algn valor distinto a undefined o null.
Esta funcin devuelve el valor x si slo se introduce x. Si tambin se introduce z, devolver la
suma de ambos.
function sumar(x: number): number
function sumar(x: number, z:number): number
function sumar(x: number, z?: number): number {
var total: number = x;
if (z != null) {
total = x + z;
}
return total;
}

Como z es el parmetro que puede estar vaco y darnos problemas, tenemos que comprobar
que realmente contiene algn valor antes de operar. En este caso vemos si y es distinto de null (o de
undefined pues el operador != comprueba haciendo conversin de tipos). Si lo es podemos operar
normalmente.

132

9.7

Funciones annimas
Las funciones annimas son aqullas que no tienen ningn nombre especificado.

(): void => { }


function () { } // Falla por no especificar un nombre

Cuando declaramos una funcin con la palaba reservada function seguido de un identificador
es lo mismo que si asignramos una funcin annima a una variable pues internamente el identificar
es una declaracin de variable.
var sumar = function () { } // es equivalente a
function sumar() { }

El ejemplo no compila pues da un error de identificador duplicado.


El problema de no tener ninguna referencia a la funcin es no poder invocarla ms de una
sola vez.

9.7.1

Expresiones lambda (funciones flecha)

TS nos proporciona otra sintaxis a la hora de declarar una funcin que resulta bastante
interesante llamada funciones flecha.
Siguiendo con el ejemplo anterior, otra forma de declarar sumar sera:
var ejemplo = (x: number): number => { return 0 };

Entre parntesis se especifica la lista de parmetros seguido de : (dos puntos) para especificar
el tipo devuelto por la funcin. Por ltimo el => para definir el cuerpo de la funcin. Realmente no
es necesario encerrarlo entre llaves {} pero si se hace debe aparecer la palabra clave return
Son equivalentes:
var ejemplo = (x: number): number => { return 0 };
var ejemplo = (x: number): number => 0;

Incluso podemos usar los parmetros en el cuerpo sin llaves:


var cuadrado = (x: number): number => x * x;

En el caso de las funciones flecha la nica posibilidad es la de asignarla a una variable pues
su sintaxis no permite darle un nombre en la propia declaracin
var funcion = (): void => {}

134

9.7.2

Tipado literal de una funcin

Hemos visto que una funcin puede almacenarse en un objeto, ya sea mediante expresiones
estndar o flechas.
La cuestin que se nos plantea es que si en TS todo est tipado, cmo se tipan las funciones?
Podemos pensar que con el tipo Function ya sera suficiente. En un principio podra ser as ya que
funciona perfectamente pero su gran inconveniente es que con l no se puede tipar de una forma ms
restrictiva, esto es definiendo una cabecera de funcin exacta.
En nuestro ejemplo:
var cuadrado = (x: number): number => x * x;

La variable cuadrado ha sido tipada por inferencia. Si no fuera as, y se nos olvidara tiparla,
resultara que a la hora de invocarla no tendramos la ayuda del editor para saber qu parmetros
tiene.
Podramos hacer esto:
var cuadrado: Function = (x: number): number => x * x;

Pero el tipado no sera tan especfico y no sabramos, a la hora de invocar la funcin, que
parmetros acepta y qu tipo de datos devuelve, si es que devuelve alguno.
Nosotros podemos tiparla de forma explcita:
var cuadrado: (x: number) => number;

Esta vez la flecha no se usa para indicar el cuerpo de la funcin, pues estamos tipando. Sino
que se utiliza para especificar el tipo devuelto. Slo podemos tipar funciones de esta forma con
expresiones flecha. Una funcin estndar tambin queda tipada por una expresin flecha:
var cuadrado:(x: number) => number = function (x: number): number {return x
*x}

9.7.3

Tipado mediante objetos literales

Adems de las formas de declarar una funcin que conocemos mediante function o las
expresiones lambda, podemos hacerlo mediante un objeto.
var funcion: { (x: number): string };

Su equivalencia es forma corta es:


var funcion: (x: number) => string;

Lo que aqu nos permite la primera forma es poder sobrecargar la funcin con ms
definiciones. La segunda forma slo permite una.
var funcion: { (x: number): string; (x: string): number } = sobrecargada

136

function sobrecargada (x: string): number


function sobrecargada (x:number):string
function sobrecargada (x:any):any{
return "sobrecargada";
}

Hemos sobrecargado la function funcion con otra definicin. Hay que tener en cuenta que en
el tipo no hay que definir una funcin que englobe a las dems.

9.7.4

Definicin de funcin por parmetro

Ahora imagina que tenemos una funcin cualquiera que tiene como parmetro otra funcin
pero con una determinada definicin. Cmo lo haramos?
function ejemplo(func: (x: string) => number): void {
//(...)
}

La funcin ejemplo acepta como parmetro una funcin slo si esa funcin acepta como
parmetro un dato del tipo string y devuelve uno del tipo number.

9.7.5

Contexto
Una funcin flecha conserva el contexto donde se ha declarado.

class A {
mostrar() {
this.mostrarLetra();
}
mostrarLetra() {
alert("A");
}
}
var a: A = new A();
var mostrar = a.mostrar;
mostrar();

La ejecucin fallar porque el contexto de la ejecucin mostrar() es window por lo que asigna
this a window. Window no tiene la funcin mostrarLetra() y falla.
Pero, sin embargo, escribimos esto:
class A {
mostrar = () => {
this.mostrarLetra();
}
mostrarLetra() {
alert("A");

138

}
}
var a: A = new A();
var mostrar = a.mostrar;
mostrar();

Funcionar correctamente. Lo que hace el compilador es referenciar el this en otra variable


llamada _this justo antes de la declaracin del mtodo. Cuando el mtodo se ejecuta y hace
this.mostrarLetra(), ese this es, en realidad, el _this que antes se cre. _this s hace referencia al
objeto en s y no a window por lo que puede ejecutar this.mostrarLetra() sin problemas.

9.7.6

Funciones annimas autoejecutables

Este tipo de funciones se pueden invocar de forma automtica encerrndolas entre parntesis
y aadiendo () al final. Mucho cuidado con hacer esto si queremos declarar y ejecutar de forma
automtica ms de una funcin porque en este caso s es necesario acabar la sentencia con ; (punto y
coma)
( (): void => { alert("funcin flecha")} )(); // ; necesario
(function () { alert("funcin") })();

9.8

Funciones que devuelven funciones


Puede una funcin devolver otra funcin con una definicin determinada? S.

function devolverFuncion(): (x: string) => number {


return fun => 1;
}

En este caso tenemos una funcin llamada devolverFuncion sin parmetros. El tipo devuelto
por la funcin es otra funcin que tiene como parmetro una variable del tipo string y su tipo de
retorno es un number.
En el return devolvemos una funcin flecha literalmente. Fun queda tipada por inferencia.

9.9

Funciones especializadas
Son aqullas que poseen un parmetro con valor por defecto y ese valor es un string.

140

function especializada(name: "espe"): string;


function especializada(name: string): any;
function especializada(name: string): number {
return 0;
}

Tras los dos puntos no se ha especificado el tipo del parmetro, sino directamente el valor
como cadena de caracteres.
De esta forma si invocamos la funcin e introducimos como argumento el valor especificado
espe, se usara exclusivamente esa definicin de funcin.
Hay que tener en cuenta que si usamos este tipo de definiciones especializadas, siempre tiene
que haber una que no lo sea y que englobe a las dems.
Esto no es vlido
function especializada(name: "espe"): string;
function especializada(name: number): any;
function especializada(name: string): number {
return 0
}

Y no lo es porque la segunda definicin tiene como parmetro un number el cual no es


compatible con string. A su vez es necesaria una tercera definicin que es la que contendr el cuerpo
de la funcin con la implementacin de la misma.

9.10

Comparando funciones

Las funciones se comparan de la misma forma que se sobrecargan. Simplemente deben


coincidir en nmero de parmetros, tipo de los mismos y devolver el mismo tipo de dato. Los tipos
no han de ser exactos, basta con que sean compatibles.
var func1: (x: number, y: number) => number = (x: number, y: number) => x * y;
var func2: (x: number) => number = (x: number) => x;
func1 = func2 // Correcto
func2 = func1 // Incorrecto

La primera asignacin es correcta porque se le est asignando a la funcin con ms


parmetros una que tiene menos y coinciden en el tipo.
La segunda asignacin es incorrecta porque ocurre lo contrario. A la funcin con menos
parmetros se le est asignando una con ms y no puede absorberlos
Esto resulta muy til a la hora de construir funciones que acepten otras funciones por
parmetro.
var numeros: number[] = [4,5,9,10];

142

Usamos el mtodo
numeros.filter() que exige como argumento una funcin con 3 parmetros: los dos primeros
son nmeros y el ltimo del tipo Array.
Es obligatorio pasarle una funcin con esa definicin? Realmente no. Como argumento
acepta una funcin con un mximo de 3 parmetros, por lo que si slo nos interesa construir una
funcin con un slo parmetro podemos hacerlo.
numeros.filter((item) => console.log(item));

144

10. Enumerados
10.1

Introduccin

Los enumerados (o enums) son un tipo derivado de number que relacionan un nombre literal
con un nmero determinado. Es una forma ms amigable que el uso de nmeros en determinados
casos.
Si queremos manejar una lista de animales podramos asociar cada uno con un nmero y usar
el mismo para referenciarlos. O bien podramos guardar el nombre del animal como string. Pero eso
no nos permite que la lista sea inamovible ni limitada y, adems, es poco manejable. Si declaramos
un enum con los nombres y los mismos se asocian de forma automtica a un nmero, estamos
consiguiendo lo que queremos.
enum Animal { Perro, Gato, Conejo }

La mecnica es la misma que la de los estticos. Para acceder a los valores del enum se
escribe el nombre del enum seguido de un . (punto) y despus el nombre de uno de los contenidos.
var perro:Animal = Animal.Perro;

Realmente los enums son nmeros. En el enum de ejemplo, Animal, el primero, Perro,
empieza por el 0 siguiendo una sucesin. Si queremos que sta cambie debemos asignrselo de
forma explcita:
enum Animal { Perro = 10, Gato, Conejo }
// Perro es el 10, Gato el 11
enum Animal { Perro, Gato = 10, Conejo }
// Perro es el 0, Gato el 11 y Conejo el 12

Cuidado con hacer esto:


enum Animal { Perro = 10, Gato = 9, Conejo }
// Perro es el 10, Gato el 9 y Conejo el 10

No falla en la compilacin pero es un error pues podramos confundir Perro con Conejo ya
que internamente se manejan con el mismo nmero.

10.2

Obteniendo el nombre del valor

Con nuestro enum de ejemplo:


146

enum Animal { Perro, Gato, Conejo }

Podemos obtener el nombre del animal como string si conocemos su nmero.


var animal: string = Animal[1]; // Gato

Los enumerados resultan muy tiles para limitar los valores que podemos usar como, por
ejemplo, si estamos desarrollando un juego 2D, el personaje slo podr ir arriba, abajo, izquierda,
derecha.
enum Direcciones { Izquierda, Derecha, Arriba, Abajo };

De esta forma, cuando queramos moverlo o comprobar hacia dnde va, sabemos que slo
tiene esas 4 posibilidades y no aceptaremos una que no est entre ellas.
Pueden usarse para tipar los parmetros de una funcin.
enum Animal { Perro, Gato, Conejo }
function mostrarAnimal(animal:Animal):void{
console.log(Animal[animal]);
}
mostrarAnimal(Animal.Perro);

148

11. Clases
11.1

Qu es una clase

Nota.En este tema hablamos de mtodos para referirnos a las funciones de una clase.

Una clase representa algo de la realidad tangible o no, como puede ser una persona, un
automvil, una vivienda o una idea. Realmente es una abstraccin de esa realidad.
Para entender bien el concepto de clase debes pensar en que es como una fbrica de cosas.
Esta fbrica construye los objetos para los que est diseada como una lnea de produccin de
coches.
Una clase es similar. Se disea para ser un molde del que despus saldrn objetos a partir de
l. Todos los objetos comparten entre s el mismo diseo pues todos se han construido a partir del
mismo molde.
En la programacin orientada a objetos el molde sera una clase y los objetos creados a partir
de l las instancias de esa clase.
La forma de decir que una variable es del tipo de una clase es de la misma forma que tipamos
una variable. A las clases tambin se les suelen llamar pues realmente se comportan como un tipo de
datos.

11.2

Creacin de clases

Se usa la palabra reservada class.


class Persona { }

La convencin de nombre para las clases es la primera letra de cada palabra es en


maysculas. Es lo que se conoce como lowerCamelCase
Ms informacin: http://es.wikipedia.org/wiki/CamelCase
Al crear nuestra propia clase (o tipo, si as se entiende mejor) podemos tipar una variable de
la misma forma que haramos con los primitivos y envoltura.
var carlos: Persona;

Con esto conseguimos que la variable de nombre carlos sea del tipo Persona.

150

El siguiente paso es, como hemos hablado en anteriores apartados, inicializar la variable.
Ahora mismo el valor de esa variable es undefined. Para inicializarla se usa el operador new seguido
del nombre de la clase y de parntesis. Este operador reserva un espacio de memoria para representar
al objeto.
var carlos: Persona = new Persona();

A esto se le llama instanciar una clase y a la variable se le puede llamar instancia.


Como hablamos anteriormente, el instanciar una clase es crear un objeto a partir del molde.
En este caso nuestro molde es Persona.

11.3

Constructores

Qu es el constructor? Realmente es un mtodo de la clase que nos permite instanciarla. TS


provee un constructor por defecto, sin parmetros.
class Persona {}

Si queremos crear uno debemos usar la palabra reservada constructor.


class Persona {
constructor() { }
}

De esta forma hemos creado nuestro constructor para la clase Persona. Se comporta de la
misma forma que cualquier funcin por lo que puede ser sobrecargada, aceptar parmetros
obligatorios, opcionales o con valor por defecto.
class Persona {
constructor(nombre: string, apellido1: string, apellido2?: string) { }
}

El constructor de la clase Persona ahora tiene como parmetros obligatorios el nombre y el


primer apellido. El segundo apellido es opcional.
var carlos: Persona = new Persona ("Carlos", "Lama");

En el cuerpo del constructor podemos usar estos valores como si de cualquier funcin se
tratara.

11.4

Estado y comportamiento

Una clase tiene atributos (se representan con variables) que definen su estado, y mtodos
(funciones) que definen su comportamiento. A cada uno de sus componentes se les llama miembro
de la clase.

152

11.4.1

El estado
Los atributos de una clase son variables que se declaran dentro de la propia clase.

Seguimos construyendo la clase Persona. Tenemos que pensar qu caractersticas tiene una
persona cualquiera, qu es lo que nos define. En este caso hemos optado por su nombre y apellidos.
Tambin podra ser el DNI, altura, peso, todo lo que queramos o necesitemos.
class Persona {
nombre: string;
apellido1: string;
apellido2: string;
constructor(nombre: string, apellido1: string, apellido2?: string) {}
}

Hemos declarado sus atributos pero no estn inicializados. Lo hacemos en el constructor.


class Persona {
nombre: string;
apellido1: string;
apellido2: string;
constructor(nombre: string, apellido1: string, apellido2?: string) {
this.nombre = nombre;
this.apellido1 = apellido1;
this.apellido2 = apellido2;
}
}

Como podemos ver lo que se introduce como argumento al constructor es lo que en su


implementacin se le asigna a los atributos. Normalmente cuando instanciemos una clase debemos
inicializar su atributos pues es lo que va a definir a ese objeto en particular y lo va a diferenciar del
resto de objetos de la misma clase.
Hay que puntualizar que las clases no aceptan atributos opcionales.
class Persona {
nombre?:string;
apellido1: string;
apellido2: string
/* () */
}

11.4.1.1 Otra forma de declarar atributos


Los parmetros de entrada de un constructor pueden ser miembros de la clase (atributos) de
forma automtica sin declararlos de forma explcita.
class Persona {
constructor(private nombre: string, private apellido1: string, private
apellido2?: string) {}

154

public mostrarNombre(): void {


alert(this.nombre + " " + this.apellido1 + " " + this.apellido2);
}
}

La diferencia ha sido la de escribir la palabra reservada private (con public tambin funciona)
en la propia definicin del mtodo constructor. De esta forma estamos declarando de forma
automtica esos atributos como miembros de la clase. Y, a la hora de introducirlos como argumentos
del constructor, ya se estaran inicializando.
El constructor siempre es pblico. Es el nico caso en que se debe omitir. En algunos
lenguajes de programacin existen los constructores privados pero en TS no estn soportados.

11.4.2

El comportamiento
Qu podemos hacer ahora? Darle un comportamiento a travs de mtodos.

Qu puede hacer una persona? Puede hablar, caminar, comer El comportamiento de una
clase suele definirse tambin como verbos. Evidentemente no todas las acciones tienen sentido en
todos los contextos. Si estamos creando la clase Persona para un registro de alumnos de un colegio,
no tiene sentido implementar un mtodo que se llame caminar. Podra tenerlo si estuviramos
desarrollando un juego.
Para el ejemplo crearemos un mtodo llamado decirNombre() que mostrar en un alert() el
nombre de la persona junto con sus apellidos.
class Persona {
nombre: string;
apellido1: string;
apellido2: string;
constructor(nombre: string, apellido1: string, apellido2?: string) {
this.nombre = nombre;
this.apellido1 = apellido1;
this.apellido2 = apellido2;
}
mostrarNombre(): void {
alert(this.nombre + " " + this.apellido1 + " " + this.apellido2);
}
}

Puedes observar que muestra la concatenacin de los atributos que hemos insertado como
argumentos a la hora de instanciar la clase.
Bien, hemos creado unos atributos y un mtodo que define un comportamiento. Cmo
accedemos a ellos? Con el operador . (punto).
Al instanciar la clase:
var persona: Persona = new Persona("Carlos", "Lama");

156

Podemos acceder a sus miembros con el nombre de la variable seguido de un punto, seguido
del miembro al que deseemos acceder. Si es un atributo.
Podemos leer el valor o modificarlo.
persona.nombre = "Carlos";

Si es una funcin podemos invocarla:


persona.mostrarNombre();

11.4.3

Operador this

Como puede ver hay un nuevo operador llamado this. this se refiere a la clase en s misma
donde se escribe y es la forma de referenciar a los miembros de la clase. Si se intentara acceder a un
miembro de clase sin anteponer this, fallara la compilacin.
La forma de utilizarlo es la misma con la que accedemos a los mtodos pblicos de una clase
por medio de una instancia de la misma, con this. (punto).

11.4.3.1 Contexto
El this en JS funciona de una forma distinta a como lo hace en la mayora de los lenguajes
orientados a objetos pues se refiere al contexto donde se ha ejecutado. Es un tema que puede traerte
de cabeza si no sabes bien cmo funciona.
Llamada

Valor de this

ejecutar();

Objeto al que pertenece

var objeto = new Objeto();

La nueva instancia

El operador this slo tiene sentido dentro de la funciones pues fuera de stas su valor siempre
es window. Ya una vez dentro de la funcin el valor de this ser el objeto al que pertenezca esa
funcin. Podemos decir que son las nicas que crean nuevos contextos.
var ejemploThis = {
nombre: "Jos",
apellido: "Lama",
nombreYApellido: this.nombre +" "+ this.apellido
}
ejemploThis.nombreYApellido // undefined undefined

El atribudo nombreYApellido del ejemplo es undefined undefined pues this est referenciando
a window y ste no tiene los atributos nombre y apellido.

158

En el caso de que lo usemos dentro de una funcin.


function ejemploThis(){
this; // window
}
ejemploThis();

De nuevo this es window porque ejemploThis() no pertenece a ningn objeto de forma


explcita, por lo que es parte de window.
El operador new cambia este comportamiento y hace que el contexto sea la instancia.
function ejemploThis(){
this; // object. La instancia.
}
var ejemplo = new ejemploThis();

Teniendo en cuenta la primera fila de la tabla, podemos hacer esto:


var ejemploThis = {
nombre: "Jos",
apellido: "Lama",
nombreYApellido: function(){return this.nombre +" "+ this.apellido}
}
ejemploThis.nombreYApellido(); // Jos Lama

En esta ocasin, la funcin s pertecene a un objeto de forma explcita por lo que ese this
referencia al contexto de la funcin, que es ejemploThis, el objeto.
Algo a muy tener encuenta es lo siguiente.
var ejemploThis = function(){
var nombre = "Jos";
var apellido = "Lama";
var nombreYApellido =
function(){
console.log(this.nombre +" "+ this.apellido)
}
nombreYApellido();
}
ejemploThis()// undefined undefined

Si echamos un vistazo a la tabla, es de suponer que this.nombre y this.apellido, que se


encuentran dentro de la funcin nombreYApellido(), deberan ser correctos pues el contexto de la
funcin es otra funcin superior que s posee esos atributos, es decir, nombreYApellido() pertecene a
un objeto (que en este caso es una funcin). Pero esto realmente no es as. El ejemplo no funciona
como parece y en su lugar muestra undefined undefined. La conslusin final es que las funciones
crean contexto pero no pueden formar parte de l a menos que se use el operador new.
160

162

11.5

Encapsulamiento

Todo miembro de una clase es pblico por defecto. Esto significa que es accesible desde
fuera de la clase. Para hacer que un miembro no lo sea, hay que declararlo como privado. Las
palabras reservadas son public y private.
Normalmente los atributos deben ser siempre privados y la forma de acceder a ellos es
mediante mtodos pblicos llamados getters y setters.
class Persona {
private nombre: string;
private apellido1: string;
private apellido2: string;
//
}

As, si creamos una instancia de la clase Persona llamada carlos y hacemos esto:
carlos.nombre = "Carlos";

Nos dara un error pues no es accesible desde fuera.


Lo mismo ocurre con los mtodos.
class Persona {
//...
private mostrarNombre(): void {
alert(this.nombre + " " + this.apellido1 + " " + this.apellido2);
}
}

Esta llamada no estara permitida:


carlos.mostrarNombre();

Es algo menos comn el encontrarse con mtodos privados. Se suelen usar para
comprobacin de datos dentro de la propia clase.
Como hemos dicho, todo miembro es pblico por defecto sin escribirlo de forma explcita
aunque es aconsejable hacerlo para darle mayor legilibidad al cdigo.

164

Nuestra clase quedara as:


class Persona {
private nombre: string;
private apellido1: string;
private apellido2: string;
constructor(nombre: string, apellido1: string, apellido2?: string) {
this.nombre = nombre;
this.apellido1 = apellido1;
this.apellido2 = apellido2;
}
public mostrarNombre(): void {
alert(this.nombre+" "+this.apellido1+" "+this.apellido2);
}
}

Para acceder a esos atributos que hemos declarado como privados, lo que suele hacer es crear
pares de mtodos pblicos por cada uno, llamados setters y getters que contenga el nombre del
atributo. Ejemplo:
public getNombre():string{
return this.nombre;
}
public setNombre(nombre:string):void {
this.nombre = nombre;
}

El mtodo getNombre() devuelve el nombre, por ello el tipo de retorno debe ser el mismo que
el de nombre. El mtodo setNombre(nombre:string) no devuelve nada porque se usa para establecer
un nuevo valor a nombre. Se exige pasar como argumento una variable del tipo del atributo.
Por qu se hace as? De esta forma podemos hacer comprobaciones antes de asignar valores
a los atributos del objeto. Si pudiramos asignar libremente, es posible que pudieran contener valores
no deseados.
En este caso un nombre no puede contener nmeros, es absurdo. Como un string acepta como
cadena cualquier cosa, habra que comprobar que no contiene nmeros. En el caso de que los
contenta no se asigna.
public setNombre(nombre:string):void{
/*Comprobacin de si es un nombre vlido. Si no lo es, no asignar*/
this.nombre = nombre;
}

As controlamos que no tenga informacin errnea.

166

11.5.1

Getters y setter implcitos

Es una forma muy interesante de construir getters y setters pues sintcticamente son
invisibles a la hora de acceder a los atributos.
En el apartado anterior hacamos esto:
public getNombre():string{
return this.nombre;
}
public setNombre(nombre:string):void {
this.nombre = nombre;
}

Ahora podemos hacer esto:


public get nombre():string{
return this.nombre;
}
public set nombre(nombre:string) {
this.nombre = nombre;
}

get y set son palabras reservadas del lenguaje. Usadas en un mtodo seguido de un espacio y
el nombre de un atributo, lo convertimos en mtodo.
Hay que tener en cuenta que el nombre del getter y setter implcito no puede coincidir con el
del atributo pues nos dara un error de duplicado.
Para evitar esto lo que se suele hacer es anteponer un guion bajo en los nombres de los
atributos. As quedara la clase Persona slo con un atributo para hacerlo ms simple:
class Persona
{
constructor(private _nombre: string ){

public get nombre(): string{


return this._nombre;
}
public set nombre( nombre: string ) {
this._nombre = nombre;
}
}

Nota: No se especifica el tipo void como devolucin de los setters implcitos, da error de
compilacin.
Para usarlos basta con acceder al atributo como si ste fuera pblico.
var carlos: Persona = new Persona( "Carlos");
persona.nombre = "Carlos";

168

As combinamos la simpleza sintctica del acceso a atributos pblicos junto con la


practicidad de hacerlo mediante mtodos.

11.6

Herencia

Qu es la herencia? Podemos imaginar que en el mundo existen diferentes tipos de cosas que
tienen estados y comportamientos comunes como podran ser los mamferos, los automviles o los
telfonos. La herencia nos provee un mecanismo para relacionar las distintas clases.
Nuestra clase ejemplo Persona se refiere a algo muy general. Podramos especificar ms. Si
estamos realizando la gestin de un aula, nos damos cuenta de que en ella hay alumnos y profesores
y ambos son personas. De esta forma estamos agrupando dos tipos de cosas bajo un mismo
comportamiento y estado.
Con todo ello podramos crear una clase llamada Alumno y otra llamada Profesor que
heredaran de Persona por lo que las clases hijas (as se les llamas a las clases que heredan de otra)
obtendran todo lo que es y hace el padre (as se les llama a las clases de las que se hereda).
Para hacerlo hay que usar la palabra reservada extends.
class Persona{}
class Alumno extends Persona { }
class Profesor extends Persona { }

Nota: no existe la herencia mltiple en TS. Esto es que una clase slo puede heredar
de una sola clase a la vez. No confundir con construir una jerarqua pues una clase
puede heredar de varias si entre todas se relacionan de forma vertical.
ALUMNO PERSONA MAMIFERO SERVIVO

Ahora tanto Alumno como Profesor obtendran todo lo que es y hace Persona. Bueno, no
todo realmente pues aqu entra en juego el princio de ocultacin. Todo lo declarado como pblico se
hereda. Todo lo declarado como privado no se hereda y no es accesible desde la clase hija. Hay un
tercer modificador, llamado protegido (protected) que no est soportado en TS. Si declaramos un
miembro como protected, las clases hijas lo heredan pero no es accesible desde fuera.

11.6.1

El operador super
Hemos visto el operador this, que hace referencia a la clase propia donde lo usemos.

Existe otro llamado super que hace referencia a la clase padre desde donde estemos
heredando. Con l podemos referenciar miembros de la clase padre siempre y cuando no sean
privados.
Imaginemos que queremos que, adems de nombre y apellidos, un alumno tenga un nmero
de alumno.

170

class Alumno extends Persona {


private numeroAlumno: number;
constructor(nombre: string, apellido1: string, numeroAlumno: number,
apellido2?: string) {
super(nombre, apellido1, apellido2);
numeroAlumno
}
}

this.numeroAlumno =

Qu ha pasado aqu?
Hemos creado un constructor para Alumno en el que admite un parmetro ms que el de
Persona para incluirle la referencia.
Hemos llamado al constructor de Persona pasndole como argumento lo que espera. Es muy
importante recalcar que la primera lnea de cdigo del constructor de una clase que hereda de otra es
una llamada super() con los argumentos que sean. De lo contrario dar error de compilacin. Y esto
tiene su lgica. Cuando creamos un Alumno realmente tambin estamos creando una Persona por lo
que para hacerlo se debe llamar al constructor de Persona.
Despus de la llamada super() podemos guardar la referencia.
Si Persona tiene el constructor sobrecargado, la llamada super() puede ser a cualquiera de las
definiciones del constructor. Simplemente hay que cumplir con los parmetros que exige.
Desde otros mtodos podemos llamar a los mtodos del padre con el mismo super. En este
caso no se exige que sea la primera llamada.
class Alumno extends Persona {
private numeroAlumno: number;
constructor(nombre: string, apellido1: string, numeroAlumno: number,
apellido2?: string) {
super(nombre, apellido1, apellido2);
this.numeroAlumno = numeroAlumno;
}

public mostrarReferencia(): void {


alert(this.numeroAlumno);
super.mostrarNombre();
}
}

En este caso hemos creado un nuevo mtodo para Alumno llamado mostrarReferencia() que
muestra la referencia del alumno y despus su nombre y apellidos. Pero esto ltimo no lo hace
reescribiendo otra vez toda la lgica, sino que se aprovecha de que el padre (Persona) ya lo tiene
implementado.
172

Hay que sealar que un objeto de una clase hija es tambin del tipo de todas sus clases padre.
En nuestro ejemplo:
ALUMNO PERSONA MAMIFERO SERVIVO
Si instanciamos Alumno obtendramos un objeto del tipo Alumno pero que a su vez tambin
sera del tipo Persona, Mamifero y SerVivo. Recuerdas la llamada super() en el constructor de
Alumno? Con eso se llama al constructor de Persona por lo que podemos deducir que estamos
creando tambin una instancia de Persona y as sucesivamente. No estamos creando 4 instancias
distintas, slo una pero con las caractersticas de todas las superclases.

11.6.2

Sobreescritura

Heredar los miembros de la clase padre no nos obliga a utilizarlos tal y como son. Podemos
redeclarar los atributos y los mtodos llmandolos de la misma forma en la clase hija. Eso s, con
ciertas restricciones.
Los miembros deben tener el mismo modificador de visibilidad por lo que si en la superclase
est declarado como public o private, en la clase hija se debe declarar igual.
class Persona {
public mostrarNombre(): void { }
}
class Alumno extends Persona { // Error
private mostrarNombre(): void { }
}

Estamos intentando sobreescribir el mtodo mostrarNombre hacindolo privado y eso no es


posible en TS. Tampoco es posible hacer lo contrario, es decir, hacer pblico un mtodo que en el
padre es privado. Tambin es aplicable a los atributos.

11.6.2.1 Sobreescritura de mtodos


Sobreescribir no es ms que declarar una funcin en el hijo con el mismo nombre que una
que ya existe en el padre. Slo es posible si el mtodo es pblico. Si es privado y lo intentamos
sobreescribir, fallar.
En nuestra clase Persona tenemos el mtodo mostrarNombre():
public mostrarNombre():void{
alert(this.nombre+" "+this.apellido1+" "+this.apellido2);
}

Podemos crear uno nuevo en Alumno con el mismo nombre. De esta forma lo estamos
sobreescribiendo.
Si queremos que el mtodo de Alumno haga lo mismo que el de Persona y, adems, algo
adicional, se debe llamar al mtodo de Persona mediante:
174

super.mostrarNombre();

Y, posteriormente, implementar el cdigo que creamos conveniente.


Es muy til para ampliar una funcionalidad que proviene de la superclase. Por motivos de
diseo podemos necesitar que la clase hija realice ms acciones en el mismo mtodo adems de las
que ya se realizaban en la implementacin del mtodo del padre.

11.7

Agregacin y composicin

Para empezar hay que concretar que las diferencias entre agregacin y composicin son
conceptuales y no se reflejan en el cdigo.
Si en la herencia establecamos una relacin de es-un, en la composicin la relacin es la de
usa-un.
Cuando empezamos a ver los miembros de una clase, pudimos observar que no slo podran
declararse variables de tipos primitivos o envoltura, sino que podamos usar los propios.
class Persona {
private direccion: Direccion;
private identificacion: Nif;
}

En la clase Alumno podemos declarar una variable direccin del tipo Direccin que agrupe
toda la informacin necesaria: calle, nmero, cdigo postal, etc. Y otra del tipo Nif que contiene el
nmero, la letra, los dgitos de control, etc. Esa relacin entre Persona y Direccin y Persona y Nif
es lo que se conoce como usa-un.
En un principio la agregacin es mucho ms utilizada que la composicin. La gran diferencia
entre ambas es que la agregacin supone una relacin dbil, es decir, los elementos relacionados
tienen vida por s solos. En la composicin uno no se entiende sin el otro.
En nuestro ejemplo de la clase Persona estaramos usando la agregacin con Direccin Por
qu? Porque una persona seguir siendo un persona aunque no tenga una direccin postal. Y su
Direccin perdurar aunque muera.
No ocurre lo mismo con el Nif. Es cierto que una persona sin Nif sigue siendo una persona
pero si sta muere, su Nif ya no ser vlido, por lo que desaparece legalmente. Podemos decir que el
Nif tiene una dependencia fuerte de Persona.
Hay autores que opinan que el uso de la composicin/agregacin es un mejor camino que la
de la herencia. Otros afirman lo contrario. No es objeto de este libro el intentar esclarecer cul es
mejor ni peor porque en mi opinin no es tan simple. El uso de uno u otro depende del diseo que le
queramos dar a nuestra aplicacin y siempre sern los problemas que se nos planteen los que
decidirn. En todo caso la virtud est en el punto medio.

176

11.8

Polimorfismo

Com su nombre indica (muchas formas) es la cualidad que tiene un objeto de un tipo de
comportarse como de otro tipo en un momento determinado.
Recordando el ejemplo:
ALUMNO PERSONA MAMIFERO SERVIVO
Podemos hacer esto:
var ser: SerVivo = new Alumno();

Por qu? Porque Alumno es-un SerVivo


Si en una funcin aceptamos como parmetro un SerVivo:
function ejemplo(ser: SerVivo): void { }

Qu pasara si la invocamos pasndole como argumento un Alumno?


ejemplo(new Alumno());

Sera correcto? S. Pues un Alumno es un SerVivo. No hay riesgo de ningn tipo pues
Alumno ha heredado de SerVivo todos los miembros pblicos por lo que estamos seguros que de los
mtodos se van a ejecutar sin problemas.

11.9

Conversin de tipos (casting)

Siguiendo con el ejemplo anterior, podemos hacer que la variable ser se convierta en un
Alumno para poder ejecutar todo lo que Alunno implementa y SerVivo no, porque en la invocacin de
la funcin introdujimos como argumento un Alumno. Ocurre que sintcticamente no tenemos
disponible los mtodos de Alumno porque el parmetro de la funcin es del tipo SerVivo, por lo que
hay que forzarlo.
function ejemplo(ser: SerVivo): void {
var alumno: Alumno = <Alumno>ser;
}

A esto se le llama casting y consiste en convertir un tipo en otro siempre y cuando estn
relacionados por una jerarqua de clases o interfaces.
interface A { }
interface B extends A { }
class C implements B { }
function conversion(casting: A): void {
var c: C = <C> casting;
}
conversion (new C());

178

Los casting se hacen encerrando el tipo al que queremos convertir entre <> seguido de la
variable que queremos convertir.
En el caso en el que queramos usar un mtodo del tipo de la variable a la que queremos
convertir directamente sin asignarlo a otra variable tenemos que usar los parntesis.
class C{
hacer(): void { }
}
function convertir(casting: A): void {
(<C> casting).hacer();
}
convertir(new C());

Como TS se basa en el tipado estructural, tambin es posible hacer conversiones de tipos que
no tengan relacin pero sean estructuralmente anlogos.
class A{
public mostrarA():void{
alert("A");
}
}
class B{
public mostrarA():void{
alert("A");
}
public mostrarB():void{
alert("B");
}
}
function mostrarLetra(letra:A):void{
(<B>letra).mostrarB();
}
mostrarLetra(new B());

El cdigo perfectamente vlido y se ejecuta sin problemas. El parmetro del tipo A de la


funcin mostrarLetra acepta como parmetro un objeto del tipo B porque B tiene todo lo de A. A
partir de ah B puede implementar todos los mtodos que quiera.

180

11.10

Ligadura dinmica

En qu consiste?
class A {
mostrarLetra () {
alert("A");
}
}
class B extends A {
mostrarLetra () {
alert("B");
}
}

Tenemos dos clases: A y B. B hereda de A. Ambas tienen definido el mtodo mostrarLetra().


En A la ejecucin de ese mtodo muestra un alert con la letra A y en B muestra la letra B.
Si hacemos esto:
var a: A = new A();
var b: B = new B();
a.mostrarLetra();
b.mostrarLetra();

Lo que obtendremos primero es A y despus B. Algo lgico.


Pero y si hacemos esto?
var a: A = new B();
a.mostrarLetra();

Qu mostrar el alert? A o B? La respuesta es B.


El trabajo se realiza en tiempo de ejecucin pues no es hasta entonces cuando se conoce qu
mtodo ha de ejecutarse: si el del padre o el del hijo.
Qu utilidad tiene esto?
La ms inmediata es que nos evita hacer el casting de tipos. Se ve mejor con un ejemplo.
Tenemos esta jerarqua de clases:
Alumno Persona Mamifero SerVivo
function mostrarNombre(ser: SerVivo): void {
ser.mostrarNombre();
}

Ejecutamos el mtodo mostrarNombre() del parmetro. Cada una de las clases de la jerarqua
tiene implementado el mtodo mostrarNombre() ya sea porque lo ha heredado o porque lo ha
sobreescrito. Por lo tanto sea cual sea el tipo que introduzcamos como parmetro en la llamada a la
182

funcin nos ejecutar el del tipo introducido y no el de SerVivo. Esto est estrechamente relacionado
con el polimorfismo.

11.11

instanceOf

Es un operador binario muy til para el manejo de clases. Comprueba si un objeto es de un


tipo determinado. Slo funciona con los tipos referencia, es decir, no funciona con los primitivos.
var x: Number = new Number(5);
x instanceof Number; // true

No funciona con los tipos primitivos, slo con los envoltura. No podemos hacer esto:
var y: number = 5;
y instanceof number; // No compila

Adems, esto dar false:


var num: Number = 5
num instanceof Number // false

El resultado de los tipos envoltura inicializados de forma literal ser false. Para que sea true
deben haber sido inicializados con su constructor como se muestra en el primer ejemplo.
Tambin pueden ser usados para nuestras propias clases.
class A{}
class B extends A{}
var a:A = new A();
var b:B = new B();
a instanceof A // true
a instanceof B // false
b instanceof A // true

El ltimo ejemplo es true porque al ser B una subclase de A, las instancias de B son a la vez
del tipo A y B.
No sirve para interfaces. Es algo que s funciona en otros lenguajes pero en TS no.

11.12

Estticos

Hasta ahora, todos los miembros que hemos creado son de instancia. Esto quiere decir que
para cada instancia que creemos de una clase, sern independientes unas de otras.
var jose: Persona = new Persona ("Jos", "Lama");
var carlos: Persona = new Persona ("Carlos", "Ponce");

184

Son dos instancias distintas de Persona en la que sus datos no tienen relacin entre s. Si
cambio el nombre de jose, carlos seguir igual que antes.
Existe un modificar llamado static que es una palabra reservada del lenguaje. Con l
conseguimos que un miembro sea accesible sin crear instancias de la misma.
class Persona {
/* (...) */
public static mostrarNombre():void{
alert("esttico");
}
}

Para acceder a los miembros estticos se hace directamente con el nombre de la clase seguido
del operador . (punto)
Persona.mostrarNombre();

Desde un mtodo esttico no se puede acceder a miembros no estticos. Y tiene mucho


sentido. Recordemos que los miembros no estticos son aqullos que pertenecen a la instancia. Si los
estticos pueden usarse sin crear ninguna instancia, cmo van a poder usar miembros no estticos?
Otra caracterstica es que los miembros estticos son transversales por lo que no cambian por
cada instancia que creemos de la clase.

11.12.1 Constantes mediante estticos


En un tema anterior se vio que TS no tiene soporte para las constantes. En Java, por ejemplo,
se usa el modificador final a la hora de declararla para hacer que su valor no se pueda modificar una
vez inicializado.
Gracias a los getters y setters implcitos se puede hacer un apao y convertir una variable
en una constante.
Imagina que en nuestra clase Persona queremos declarar una constante pblica que guarde la
esperanza de vida media.
Basta con declararlo como privado y slo crear el getter pero no el setter.
class Persona {
private static _EV: number = 80;
public static get EV(): number {
return Persona._EV;
}
}

Podemos consultarla pero no modificarla pues slo tiene disponible el getter.


Persona.EV = 90; // No muestra error pero no hace nada

186

11.13

Clases literales

Las clases se pueden representar como un objeto. Tanto los atributos como los mtodos
pueden ser parte de un objeto estndar de TS. La forma ms fcil de representarlo es mediante un
objeto literal encerrando entre llaves. Entre las restricciones estn el no poder hacer los miembros
privados ni estticos.
class Persona {
nombre: string;
edad:number,
}
var persona: Persona = new Persona ();

Es equivalente a:
var persona: { nombre: string; edad: number };

Incluso son intercambiables:


var persona: { nombre: string; edad: number } = new Persona();
var persona: Persona = {nombre: "Carlos", edad: 25 };

No es necesario definir constructores en el objeto literal porque los mismos sirven para
inicializar los atributos. Como un objeto se inicializa asignando valores directamente a sus atributos,
no son necesarios.

11.14

Las partes de una clase

Una clase tiene dos partes bien diferenciadas: una de instancia y otra de clase o esttica.
Si creamos una clase:
class Persona {
public static esperanza_vida: number = 80;
public nombre:string;
constructor(){}
}

Parte de instancia: el atributo nombre.


Parte esttica: el atributo esperanza_vida y el constructor.
La parte esttica se referencia con el nombre de la clase por ello no podemos asignar la parte
esttica a una variable del tipo A.
var estaticaPersona: Persona = Persona; // Error

Y no es posible porque Persona es un tipo en s mismo. El tipo de Persona es otro distinto y


no Persona. Slo las intancias de Persona son del tipo Persona.
188

var estaticaPersona: typeof Persona = Persona;

Observando el cdigo JS que genera es ms sencillo de entender.


var Persona = (function () {
function Persona () {}
return Persona;
})();
var estaticaPersona = Persona;

Podemos ver que el tipo de Persona es realmente una funcin. Esto se puede comprobar con
el operador typeof
typeof Persona // function

Una vez que tenemos la referencia de la parte esttica podemos acceder a su constructor y sus
miembros estticos:
var persona = new estaticaPersona(); /* La inferencia tipa con Persona */

11.15

Objetos dinmicos

Todo objeto en TS es dinmico. Esto quiere decir que podemos aadirle atributos en tiempo
de ejecucin con la sintaxis adecuada.
class Persona{}
var carlos:Persona = new Persona();
carlos["edad"] = 26;
var edad = carlos["edad"]; // any

A la instancia llamada carlos le hemos aadido un atributo de nombre edad que inicializamos
con el nmero 26. Esto es totalmente vlido y podemos aadir cuantos queramos.
Es evidente que de esta forma perdemos todo resquicio de tipado pues no sabemos qu va a
devolver una vez accedamos al atributo edad por eso la inferencia tipa la variables edad con Any. TS
intenta controlar esto con los diccionarios.
class Persona {
[index: string]: number;
}
var carlos: Persona = new Persona();
carlos["edad"] = 26;
var edad = carlos["edad"]; // number

Conseguimos saber qu tipo de datos va a devolver que en este caso es number. La inferencia
ha hecho su trabajo.

190

Podemos tener como mximo dos indexaciones: una por string y otra number.
class Diccionario {
[index: string]: string;
[index: number]: string;
}

La nica restriccin es que el tipo devuelvo por la numrica sea compatible con el de string.
class Diccionario {
[index: string]: string;
[index: number]: number; // Error
}

El tipo devuelto por [index: number] es number que no es compatible con string.
La compatibilidad se gestiona de la misma forma que ya hemos estudiado las
compatibilidades de primitivos, objetos, etc.
De esta forma podramos crear lo que en otros lenguajes, como PHP, se llaman arrays
asociativos, donde el ncide no es numrico, sino una cadena de caracteres.

192

12. Interfaces
12.1

Introduccin

Qu son las interfaces? Son meros contratos que se hacen para una clase. Realmente las
interfaces son listas de miembros que obligatoriamente debe tener la clase que implementa esa
interfaz.
Para qu se utilzan las interfaces? Ciertamente es un debate abierto en el mundo del diseo
de aplicaciones. Mi opinin se deberan usar para dar un comportamiento comn a clases que no
pueden tener (o no tiene sentido que tengan) relacin por herencia.
Podemos tener la clase Persona y la clase Coche. Es evidente que encontrar una relacin por
herencia entre esas dos clases no slo es complicado, sino que carece de sentido. Pero lo que s es
cierto es que pueden tener algn comportamiento comn. Tantos las personas como los coches se
desplazan. Ambos podran tener un mtodo llamado desplazar() que haga moverse al objeto en
cuestin.
Ahora imaginemos que estamos desarrollando un juego en el que hay partes mviles en el
escenario como son personas y coches. En un momento dado necesitamos que un grupo de personas
y de coches se muevan. Si ambas clases implementan la interfaz Desplazable, basta con recorrer
todos los que queramos mover y ejecutar el mtodo desplazar() sin importar si es una persona o un
coche, pues la implementacin del mtodo estar definida en cada clase de una forma particular.

12.2

Declaracin e implementacin

Para crear una interfaz se usa la palabra reservada interface.


interface Desplazable { }

Para que una clase implemente una interfaz se utiliza la palabra reservada implements:
class Persona implements Desplazable {
//...
}

La interfaz Desplazable est vaca por lo que no est obligando a la clase Persona a hacer
nada. Pero si en Desplazable definimos un mtodo:
interface Desplazable {
desplazar (): void;
}

194

Obligamos a la clase Persona a implementarlo. Si no lo hace dar error de compilacin. Para


ello hay que cumplir exactamente con la definicin del mtodo. Si devuelve un number no podemos
implementar ese mtodo devolviendo un string. En este caso no devuelve nada por lo que as debe
ser:
class Persona implements Desplazable {
//(...)
public desplazar(): void { }
}

La interfaz no obliga a una implementacin especfica del mtodo, esto depender en cada
situacin. As pues 10 clases distintas pueden implementar Bipedo siendo el cuerpo del mtodo
distinto en todas ellas.
Cabe decir que al contrario de la herencia de clases, s se permite la implementacin mltiple
de interfaces.
class Persona implements Desplazable, Inteligente{
//(...)
}

Por otro lado no slo puedes obligar a implementar mtodos, sino tambin a poseer atributos.
interface Desplazable {
velocidad: number;
desplazar(): void;
}

Los atributos pueden ser opcionales por lo que no obligara a la clase a implementarlos.
interface Desplazable {
velocidad?: number;
desplazar(): void;
}

Las interfaces no pueden contener miembros privados o estticos.


interface Desplazable {
velocidad?: number;
private desplazar(): void; // Error de compilacin
}

12.3

Herencia

Existe tambin la herencia de interfaces mediante extends como vimos en el tema de las
clases.
interface Desplazable extends Motriz { }

196

Si una clase implementa la interfaz Desplazable, no slo debe implementar todo lo que le
obliga Desplazable, sino tambin todo lo de Motriz. Las reglas de sobreescritura son las mismas que
para las clases.
Una clase que herede de otra clase que implemente una interfaz, estara tambin
implementndola de forma implcita.
class Persona implements Desplazable, Inteligente {
//(...)
}
class Alumno extends Persona {
//(...)
}

La clase Alumno estara implementando las interfaces Desplazable y Motriz a travs de


Persona, que es clase padre.

12.4

Interfaces literales

Al igual que ocurra con las clases, las interfaces se pueden escribir como un objeto literal.
interface A {
nombre: string;
}

Es equivalente a:
var B: { nombre: string };

Pero una clase no puede implementar una interfaz definida como objeto literal, no la reconoce
como tal.
var N: { nombre: string };
class C implements N { // No reconoce N como una interfaz
nombre: string;
}

12.5

Interfaces como funciones

Podemos usar las interfaces como definiciones de funciones.


interface Funcion {
(x: number, y: number): number;
}

Podemos tipar una variable con esa interfaz e inicializarla con una funcin que cumpla con la
definicin:
198

var func: Funcion = function (x: number, y: number) {return x * y }

Su utilidad es limitada y est orientado a la creacin de archivos de definicin para libreras


JS.

12.6

Fusionando interfaces

Puede declarar dos interfaces con el mismo nombre sin ningn problema. stas se fusionarn
en una sola donde sus miembros ser la combinacin de todos.
No se puede tener atributos con nombre repetidos tal y como ocurre en una interfaz nica.
Los mtodos, sin embargo, s pueden repetirse por lo que se aplicaran las reglas de sobrecarga de
funciones.

12.7

Comprobar si una clase implementa una interfaz

Como ya vimos, los operadores instanceof y typeof no funcionan con las interfaces entre otros
motivos porque no existen en JS. Es un invento de TS que no produce cdigo alguno al compilar por
lo que todas las comprobaciones son en tiempo de compilacin.
Eso nos plantea un problema a tener cuenta pues no podemos, a priori, comprobar si un
objeto es del tipo de una interfaz concreta.
En la documentacin oficial de TS asumen este problema y recomiendan que se comprueben
todos los miembros de una interfaz. Esto supone un inconveniente pues podemos comparar
miembros que casualmente tambin estn en otra interfaz distinta. Para asegurarnos al 100%, es
preferible hacer un casting de ese objeto hacia la interfaz, encerrado en una estructura try-catch. Si
no lanza ninguna excepcin, significa que s la implementa.

200

202

13. Genricos
13.1

Introduccin

Los genricos permiten parametrizar directamente las clases e interfaces. Son un paso ms en
la abstraccin.
Hasta ahora habamos definido clases no genricas como Concesionario:
class Concesionario { }

Esta clase es capaz de englobar todos los concesionarios de las marcas de los coches. En ella
iremos guardando una lista de los coches de cada concesionario.
Pero para qu marcas de automviles disearemos la clase? Podemos hacerlas para todas
con el uso de genricos.
class Concesionario<T>{
private coches: Array<T>;
constructor(){
this.coches = new Array<T>();
}
public getCoche(indice: number): T {
return this.coches[indice];
}
}

Para hacerlo se aade <T> despus del nombre de la clase. Realmente puedes escribir lo que
quieras, no necesariamente una T. Ademas puedes parametrizar con una lista si te hace falta:
class Concesionario<T, V, K>{ }

Tenemos, por ejemplo, la clase Seat:


class Seat { }

Vamos a crear un concesionario de Seat:


var concesionarioSeat: Concesionario<Seat> = new Concesionario <Seat>();

Como puedes ver hemos usado la clase Seat para parametrizar el genrico. De esta forma
donde la clase es T, ahora es Seat.
204

Clase original:
class Concesionario<T>{
private coches: Array<T>;
constructor(){
this.coches = new Array<T>();
}
public getCoche(indice: number): T {
return this.coches[indice];
}
}

Clase al sustituir T por Seat:


class Concesionario<Seat>{
private coches: Array<Seat>;
constructor(){
this.coches = new Array<Seat>();
}
public getCoche(indice: number): Seat {
return this.coches[indice];
}
}

El compilador sustituye el parmetro genrico T por la clase que le hemos proporcionado, en


este caso Seat. A este proceso se le llama instancia de tipo genrico.
Hemos conseguido que el array de coches de la clase sea de coches de la marca Seat. Lo
mismo si lo hacemos con otras marcas:
class Audi { }
class Ferrari { }
var conceAudi: Concesionario<Audi> = new Concesionario <Audi >;
var conceFerrari: Concesionario<Ferrari> = new Concesionario < Ferrari >;

13.2

Restricciones en los parmetros

Vamos un paso ms all y vamos a restringir qu clases pueden ser parmetros de


Concesionario.
La restriccin del tipo de clase se hace por herencia.
class Concesionario<T extends Automovil>{
//(...)
}

De esta forma slo aceptamos como parmetros para la clase Concesionario una clase que
herede de Automovil porque en nuestros concesionarios no se venden otra cosa.
206

class Avion { }
class Automovil { }
class F18 extends Avion { }
var conce: Concesionario<F18> = new Concesionario < F18>; // Error

Es errneo porque F18 no hereda de Automvil por lo que no cumple con la restriccin.

13.3

Genricos en interfaces

Tambin se pueden parametrizar las interfaces de la misma forma que las clases.
Nuestra clase de ejemplo Concesionario va a implementar una interfaz llamada
IConcesionario que acepte el mismo parmetro.
interface Concesionario<T> {
getCoche(ndice: number): T;
}
class Concesionario<T extends Automovil> implements IConcesionario<T>{
//(...)
}

Como hemos dicho, al sustituir el parmetro T por lo que queremos, se hace en todas las
ocurrencias de T. Con el ejemplo de Seat quedara as:
class Concesionario<Seat extends Automovil> implements
IConcesionario<Ferrari>{
//(...)
}

Hay que aclarar que estos ejemplos sustituyendo la T de forma manual son simplemente para
mostrar lo que hace el lenguaje.
Se puede hacer que la restriccin de parmetro sea por interfaz y no por herencia? S, con la
misma palabra extends.
Cambiamos la clase Concesionario para que su restriccin se base en la interfaz IAutomovil
Tan fcil como:
class Concesionario<T extends IAutomovil> implements IConcesionario<T>{
//(...)
}

Ahora todas las clases que implementen la interfaz IAutomovil son susceptibles de ser
introducidas como argumento y si no lo hacen no sera aceptada.
class Automovil implements IAutomovil { }
class Seat extends Automovil { }

208

var conceSeat: Concesionario<Seat> = Concesionario < Seat >;

En este caso sera correcto porque aunque Seat no implementa la interfaz IAutomovil de
forma explcita, lo hace a travs de su superclase.

13.4

Funciones genricas

No slo las clases o interfaces pueden ser genricas, las funciones o mtodos tambin.
La mecnica es la misma:
function arrayDeObjetos<T>(c: T, a?: T[]): T[] {
a = a || new Array<T>();
a.push(c);
return a;
}

Para invocarla se hace de la misma forma.


var autos : Automovil[] = arrayDeObjetos <Automovil> (new Automovil());

13.5

Comparando genricos

La comparacin de genricos se hace de la misma forma que las funciones, clases e


interfaces. Lo que hay que tener en cuenta es que se hace una vez se han sustituidos los parmetros
genricos. Si dos clases son estructuralmente anlogas una vez hecho, son compatibles.
Este ejemplo es correcto.
interface Generico < T > {}
var x: Generico<string>;
var y: Generico<number>;
x = y; // Correcto

Y lo es porque la T de la interfaz genrica no se utiliza por lo que si comparamos las


interfaces despus de resolver el genrico, nos damos cuenta de que son equivalentes.
Sin embargo, si hacemos esto:
interface Generico < T > {
algo:T;
}
var x: Generico<string>;
var y: Generico<number>;
x = y; // Incorrecto

No sera correcto pues la x tendra su miembro algo del tipo string y la y tendra su miembro
algo del tipo number. Number y string no son compatibles.
210

Los genricos no son nada por s solos, sino que siempre son una clase, interfaz o funcin.
Las comparaciones se realizan una vez se resuelven los parmetros genricos siguiendo las mismas
reglas de comparacin vistas en el libro.

212

14. Tipado estructural


14.1

Ms sobre la comparacin de objetos

El tipado en TS es estructural y no nominal. Esto quiere decir que los tipos no se diferencian
por su ruta cualificada la cual incluye el nombre, sino por su estructura interna. De esta forma la
comparacin se hace miembro a miembro en nombre y tipo.

14.2

Comparando clases

El tipado estructural permite comparar clases o intercambiarlas aunque no tengan una


relacin de herencia entre ellas.
Los miembros estticos y el constructor se ignoran a la hora de la comparacin.
class Persona {
static EV: number;
nombre: string;
}
class Perro {
nombre: string;
}
var persona: Persona;
var perro: Perro;
persona = perro; // Correcto
perro = persona; // Correcto

Si alguna de las clases tiene algn miembro privado la comparacin difiere:


class Persona {
private nombre: string;
}
class Perro {
private nombre: string;
}
var persona: Persona;
var perro: Perro;

214

persona = perro; // Incorrecto


perro = persona; // Incorrecto

No son compatibles porque tienen un miembro privado. No importa si lo tienen los dos o slo
uno, lo que importa es que lo tienen. Para que dos clases sean iguales teniendo miembros privados
stos deben ser los mismos.
class Animal {
private nombre: string;
}
class Perro extends Animal { }
var animal: Animal;
var perro: Perro;
animal = perro; // Correcto
perro = animal; // Correcto

Es correcto porque el miembro privado de Perro (aunque parezca que no tenga porque
recordemos que los miembros privados no se heredan) es el mismo que el de Animal ya que hereda
de l. Si a Perro le aadimos un miembro privado con el mismo nombre que el de Animal, no
compilara pues se llama igual y no lo permite.
Si a Perro le aadimos un miembro privado de distinto nombre:
class Animal {
private nombre: string;
}
class Perro extends Animal {
private raza: string;
}
var animal: Animal;
var perro: Perro;
animal = perro; // Correcto
perro = animal; // Incorrecto

A animal se le puede asignar perro porque Perro tiene todo lo de Animal, aunque tambin
posee miembros adicionales. Pero a perro no se le puede asignar animal porque a Animal le falta el
miembro privado adicional que posee Perro, raza. La mecnica es la misma que en el apartado de las
interfaces y objetos literales: el objeto con ms miembros puede ser asignado al objeto con menos
pero no al revs.

14.3

Comparando interfaces

La comparacin de interfaces se hace igual que la comparacin de clases: miembro a


miembro. Aunque resulta ms simple por no tener miembros privados.
216

Esto es correcto:
interface A {
name: string;
}
interface B {
name: string;
}
var a: A;
var b: B;
a = b;
b = a;

De nuevo se aplica la mxima en las comparaciones de objetos: el objeto con ms miembros


puede ser asignado al objeto con menos, pero no al revs.
interface A{
nombre: string;
print();
}
interface B {
nombre: string;
}
var a: A;
var b: B
a = b; // Falla
b = a;

14.4

Clases implementando otras clases

class A {
nombre: String;
public hacerAlgo(): void { }
}
class B implements A {
nombre: String;
public hacerAlgo(): void { }
}

Para ello se hace como si de una interfaz se tratara, con la palabra reservada implements. La
clase que implementa otra se comporta como una interfaz, es decir, debe implementar sus mtodos y
atributos.
218

En nuestro ejemplo, la clase B debera implementar el mtodo hacerAlgo(). Los estticos y


privados no se tienen en cuenta del mismo modo que en una interfaz no se pueden declarar.

14.5

Interfaces herendando de clases

En TS podemos hacer que una interfaz herede de una clase. En este caso la interfaz hereda los
miembros pero no su implementacin porque una interfaz no puede contener implementaciones.
class A {
public name: string;
}
interface I extends A{ }

Qu ocurrira si la clase contiene miembros? Como hemos visto en apartados anteriores,


aunque los miembros privados no se heredan, realmente s estn presentes en las clases hijas aunque
no accesibles. Por ello la interfaz lo contendra pero con una curiosa consecuencia:
class A {
private name: string;
}
interface I extends A{ }

Slo las clases que hereden de A podrn implementar la interfaz I y no otras pues sern las
nicas que contengan el miembro privado original.
class A{
private nombre: string;
}
interface I extends A{ }
class B extends A implements I { } // Correcto
class C implements I { } // Error. C No es subclase de A

Muestra un error indicando que C no est implementando todos los miembros de la interfaz I,
concretamente el atributo nombre. Aunque declaremos un atributo nombre de tipo string y privado
en la clase C, no conseguiramos que compilara. El nico que le sirve es el de la clase A y slo se
puede conseguir heredando de ella.

220

15. Control de errores


15.1

Introduccin

Existe una forma de capturar los errores que se produzcan en nuestra aplicacin y darle
respuesta a los mismos de una forma controlada. En otros lenguajes se les llama excepciones pero en
TS se llaman errores.
Para capturar uno se utiliza la estructura try-catch, encerrando en el try el cdigo susceptible
a fallar.
try {
// cdigo
} catch (e) {
// tratar el error
}

Si algo de lo que se ejecuta falla y lanza una excepcin, se ejecutar el cdigo encerrado en el
bloque catch. El parmetro de catch es del tipo Error pero no se tipa de forma explcita. Si se hiciera
fallara al compilar.

15.2

Tipos de errores

Hay algunos ya predefinidos que resultan muy tiles. Cabe decir que todos heredan de Error.

EvalError
Indica un error al ejecutar la funcin global eval().

RangeError
Indica que estamos tratando de acceder a un ndice que no existe. Es aplicable a los arrays y a
los objecs.

ReferenceError
Indica que estamos referenciando a una variable no declarada.

222

SyntaxError
Indica que hay un error de sintaxis.
TypeError
Indica que estamos tratando de acceder a miembros de algo que vale null o que no hemos
pasado
la
variable
con
el
tipo
correcto
como
argumento.
Todos comparten una serie de atributos como el message, que describe el error de forma
literal.
Normalmente, los navegadores modernos describen estos errores de forma automtica en su
consola sin necesidad de que el desarrollador lo tenga que hacer de forma explcita.

15.3

Lanzando errores

En el bloque catch se puede ejecutar el cdigo que se desee, como por ejemplo escribir en la
consola para obtener informacin sobre l. Aunque tambin se puede lanzar el error con el operador
throw.
Lanzar un error consiste en elevarlo hacia arriba confiando en que exista un try-catch que lo
tratar de forma adecuada.
function ejemploError(): void {
var ejemplo = null;
try {
ejemplo.edad = 10;
} catch (e) {
throw e; // TypeError
}
}
try {
ejemploError();
} catch (e) {
console.error(e) /* Mostramos el error */
}

La variable ejemplo no tiene el atributo edad por lo que se lanza un error que capturamos con
catch. En el ejemplo hemos decidido seguir lanzando hacia arriba el error para que sea otra entidad
la que lo controle. Para esto no es necesario escribir el bloque try-catch dentro de la funcin, basta
con encerrar la invocacin a la misma.
function ejemploError(): void {
var ejemplo = null;
ejemplo.edad = 10;
}

224

try {
ejemploError();
} catch (e) {
console.error(e) /* Mostramos el error */
}

Lo errores que no capture nuestro cdigo, lo sern por el navegador. En las versiones ms
modernas lo hacen de una forma excelente mostrando en la consola el tipo de error y dnde.
Cuando se lanza un error, el flujo de ejecucin se para en ese punto para seguir en el bloque
que ha capturado ese error. Si tenamos ms cdigo que ejecutar, no lo har.

15.4

Lanzando errores manualmente

Podemos crear instancias de alguna clase de Error y lanzarlos para mejorar la robustez de
nuestro cdigo.
Imagina que estamos creando un ndice en el que el nmero no puede ser menor de 0.
function getVal(index: number): string {
if (index < 0) {
throw new RangeError("El ncide no puede ser menor de 0");
}
// (...)
return;
}

Como ves, hemos lanzado nuestro propia RangeError para informar de que el ndice no
puede ser menor de 0.Es decisin del programador capturar o no el error mediante try-catch y
tratarlo de forma adecuada.

15.5

Finally

Como hemos dicho, al lanzar un Error con throw se corta el flujo del programa y sigue por
niveles superiores. Aunque podemos realizar una ltima accin antes de que eso ocurra con un
bloque finally que es un aadido al try-catch. Realmente el cdigo encerrado en el finally se
ejecutar haya o no error.
function ejemploError(): void {
var ejemplo = null;
ejemplo.edad = 10;
}
try {
ejemploError();
} catch (e) {
console.error(e) /* Mostramos el error */
throw e;

226

console.info("No se muestra");
}

En el ejemplo no se llega a mostrar el mensaje No se muestra pues se ha lanzado el Error


con un throw. Pero si le aadimos el finally.
function ejemploError(): void {
var ejemplo = null;
ejemplo.edad = 10;
}
try {
ejemploError();
} catch (e) {
console.error(e) /* Mostramos el error */
throw e;
console.info("No se muestra");
}
finally{
/* Se ejecuta siempre*/
console.info("finally");
}

228

16. DOM
16.1

Introduccin

La manipulacin de las pginas webs es uno de los usos ms habituales que se le da a JS.
Mediante una API llamada Document Object Model (DOM) podemos moldear a nuestro gusto el
contenido de documentos HTML y XML. Esta API nos proporciona una serie de objetos con
atributos y mtodos muy tiles a la hora de obtener informacin de la estructura de la pgina y su
contenido.
Documentos XHTML (HTML y XML) se dividen en nodos jerrquicos, de forma que
siempre uno est dentro de otro superior. Estos estn representados, entre otros, por etiquetas HTML
como <a> o <div>. El objeto window es el que est posicionado en la parte superior de esta jerarqua.
ste contiene al objeto document que el que posee los mtodos necesarios para la manipulacin del
DOM.

http://es.wikipedia.org/wiki/Document_Object_Model

16.2
16.2.1

Document
Seleccionar elementos

Podemos referenciar elementos con variables fcilemente. De esa forma podmos


manipularlos directamente desde la variable pues representa al elemento en cuestin.
230

16.2.1.1 getElementById()
Seleccionar el elemento cuyo atributo id coincida con el proporcionado como argumento.
var div = document.getElementById("capa");

La variable div queda tipada con HTMLElement porque no es posible que por inferencia se
tipe la variable div de forma exhaustiva. Para ellos debemos hacer una conversin si conocemos qu
elemento posee ese id.
var div = <HTMLDivElement> document.getElementById("capa");

No todos los elementos tienen su propia interfaz. Algunos deben tiparse con HTMLElement.

16.2.1.2 getElementsByTagName()
Selecciona todos los elementos que coincidan con el nombre de la etiqueta proporcionada
como argumento.
var divs = document.getElementsByTagName("div");

Es una funcin especializada porque introduciendo div como argumento el tipo devuelto es
NodeListOf<HTMLDivelement>
Devuele un NodeListOf<T> que podemos recorrer con bucles somo si de un array se tratara.

16.3

Crear elementos

Se pueden crear elementos dinmicamente y aadirlos a la vista.


var capa = document.createElement("div");

Al ser una funcin especializada tipa por inferencia la variable capa con HTMLDivElement.
Una vez hecho, slo debemos aadirlo como hijo a algn elemento que actuar como padre
con appendChild()
var capa = document.createElement("div");
var body = document.getElementsByTagName("body")[0];
body.appendChild(capa);

16.4

Eliminar elementos

Para eliminar un elemento se debe borrar como elemento hijo del padre que tenga. Como no
sabemos, a priori, quin es su padre, lo ms cmodo es usar el atributo parentNode y, posteriormente,
removeChild
232

var capa = document.createElement("div");


capa.parentNode.removeChild(capa);

16.5

Acceso a los atributos

Desde las propias variables que hacen referencia a los elementos del DOM se puede acceder a
los atributos.
var enlace = <HTMLAnchorElement> document.getElementById("enlace");
enlace.href = "http://www.google.es";

La clase HTMLAnchorElement posee un atributo llamado href que almacena la direccin


hacia donde se debe navegar una vez se ha pulsado en el enlace. De esta forma podemos asignrsela
o modificarla de forma dinmica.
Los estilos tambin se pueden modificar con el atibuto style.
enlace.style.textDecoration = "none";

De esta forma eliminamos el subrayado caracterstico de los enlaces.

234

17. Eventos
17.1

Introduccin

Los eventos son sucesos que ocurren durante la ejecucin de la aplicacin. Pueden dispararse
debido a una interaccin del usuario o como respuesta a determinadas acciones de nuestro programa.
Cuando un usuario hace click del ratn sobre un botn o cuando pulsa una tecla, o cuando la
aplicacin ha terminado de cargar, se lanzan eventos.
Para ciertos eventos nos interesa darle una respuesta mediante una funcin. Son los llamados
handlers (manejadores) y para ello hay que asociar un listener (oyente) a los elementos susceptibles
de lanzarlos.
Por ejemplo, nos puede interesar que si un usuario pulsa un botn se le abra una ventana
emergente mostrando alguna informacin.
Se pueden distinguir dos tipos de eventos: visuales y no visuales.

17.2

Eventos visuales

En el estndar de la w3c estos eventos siguen un


Imagina que tenemos un enlace A dentro de un Div y ste dentro del Body.

camino

determinado.

Body
A DIV BODY

17.2.1

Div
A

Fase de captura

Cuando el usuario pulsa el enlace, un evento del tipo click es lanzado desde el punto ms alto
de la jerarqua del enlace. El punto ms alto de esta jerarqua siempre es window.
WINDOW

DOCUMENT HTML BODY DIV

Su forma de propagacin es lineal. De esta forma va recorriendo todos esos elementos uno
tras otro.
236

17.2.2

Fase de objetivo
El evento llega a quien lo dispar, en este caso el enlace.

17.2.3

Fase de burbuja
El evento vuelve hacia window por el mismo camino que lleg pero en sentido contrario.
DIV BODY HTML DOCUMENT WINDOW

17.2.4

Aadir respuesta a los eventos.

Cuando un evento se va propagando por los distintos elementos y fases, se van ejecutando los
handlers que tiene asociados.
Seguimos con nuestro enlace. Suponiendo que hemos guardado su referencia en una variable
de nombre enlace, la forma de aadir una respuesta a un evento determinado sera aadiendo lo que
se denomina listener (oyente):
enlace.addEventListener(tipoEvento:string, handler:Function, captura:boolean);

El tipo de evento es un string, en este caso podra ser click.


El handler es la funcin que se ejecutar cuando el evento llegue al enlace.
Captura es un boolean que determina si el handler se va a ejecutar en la fase de captura.
enlace.addEventListener("click", respuestaClick , true);
function respuestaClick(evt: Event): void {
alert("enlace");
}

Puedes registrar tantos como quieras para el mismo evento o para otros pero debes tener en
cuenta que los listeners se registran en orden.
Cada vez que pulsemos, saltar una ventana con el texto Pulsado.
Podemos hacer que se ejecuten handlers asociados a elementos de la jerarqua del botn
durante el camino de este evento. Suponiendo que el div que contiene al botn lo hemos referenciado
mediante una variable llamada capa
capa.addEventListener("click", respuestaClickCapa , true);
enlace.addEventListener("click", respuestaClickBoton , true);
function respuestaClickCapa(evt: Event): void { alert("capa"); }
function respuestaClickBoton(evt: Event): void { alert("botn"); }

Como hemos visto, al hacer click sobre el botn el evento recorre el camino que va desde
window al propio botn. Capa contiene a enlace por lo que se le notificar el evento click. Como
238

hemos asociado un handler, en el momento en el que pulsemos el botn, se ejecutar


respuestaClickCapa en primer lugar y respuestaClickBoton en segundo lugar. Por qu? Porque al
aadir el listener, pasamos true como argumento a capture que quiere decir que se ejecutar en la
fase de captura. Recordemos que la fase de captura es anterior a la de objetivo.
Si en vez de pasar true, hubiramos pasado false, primero se ejecutara el handler de botn y
despus el de capa pues la fase de burbuja es posterior a la de objetivo.
17.2.5

Parmetros de los handlers

Las funciones que se ejecutan en respuesta a algn evento pueden tener en su definicin un
parmetro del tipo Event. En nuestro ejemplo sera del tipo MouseEvent.
enlace.addEventListener("click", respuestaClickBoton , true);
function respuestaClickBoton(evt: MouseEvent): void { alert("enlace"); }

El argumento es pasado por el motor de eventos del navegador sin que nosotros tengamos que
intervenir.
Resulta de gran ayuda pues contiene informacin muy valiosa y, a la vez, permite influir
sobre el evento.

17.2.6

Target y currentTarget

Una de las propiedades ms tiles de un objeto del tipo Event (y todos sus hijos) es target y
currentTarget.
Target es el elemento que dispar el evento y currenTarget es el elemento por donde est
pasando el evento en esos momentos.
capa.addEventListener("click", respuestaClickCapa , true);
enlace.addEventListener("click", respuestaClickEnlace, true);
function respuestaClickCapa(evt: Event): void {
evt.target /* Es el enlace pues es quien dispar el vento */
evt.currentTarget /* Es el div capa, pues es por donde est pasando el
evento */
}
function respuestaClickEnlace(evt: Event): void {
evt.target /* Es el enlace pues es quien dispar el evento */
evt.currentTarget /* Es el botn, pues es por donde est pasando el
evento */
}

Como habrs podido observar, target y currentTarget son el mismo elemento cuando el
evento llega al quien lo dispar.

240

Esas dos propiedades son del tipo node al que podemos hacer un casting para convertirlos en
el elemento del tipo original.
function respuestaClickCapa(evt: Event): void {
var capa = <HTMLDivElement> evt.currentTarget;
}

17.2.7

El uso del this

Cuando se ejecuta un handler en respuesta a un evento, this referencia al elemento al que se


le registr el listener.
function respuestaClickBoton(evt: Event): void {
// Aqu this sera igual a evt.target
}

Eso supone un problema importante si se registran mtodos de un objeto donde se invoquen


otros mtodos del propio objeto.
class A {
respuesta() {
this.algo();
}
algo() { }
}
var a: A = new A();
enlace.addEventListener("click", a.respuesta , true);

Cuando se pulse enlace, se ejecutar a.respuesta() que en su implementacin llama a


this.algo(). El problema es que esto fallar porque ese this no har referencia a la instancia, sino que
ser enlace.
Para evitarlo se deben usar expresiones lambda.
En JS es comn usar el this para trabajar con quien dispar el evento. Mi recomendacin es
que siempre se usen las propiedades target y currentTarget que nos proporciona Event.

17.2.8

Parar la propagacin de un evento

En cada handler que se ejecuta se puede parar la propagacin del evento y hacer que deje de
seguir su curso natural. Para ello ejecutamos el mtodo stopPropagation() de Event.
capa.addEventListener("click", respuestaClickCapa , true);
enlace.addEventListener("click", respuestaClickEnlace , true);
function respuestaClickCapa(evt: Event): void {
evt.stopPropagation();
}

242

function respuestaClickEnlace(evt: Event): void {


// No se ejecuta
}

capa tiene asociado un listener en captura por lo que se ejecutar antes que el de enlace. Si
en la funcin de respuesta ejecutamos el mtodo stopPropagation() del evento disponible como
parmetro, ste interrumpir su camino y nunca llegar a enlace.

17.2.9

Parar la propagacin hacia otros listeners del mismo elemento y evento

Si stopPropagation() para la propagacin del evento totalmente, stopInmediatePropagation()


slo evita la ejecucin de otros handlers del mismo tipo de evento y elemento.
capa.addEventListener("click", respuestaClickCapa , true);
capa.addEventListener("click", respuestaClickCapa2 , true);
enlace.addEventListener("click", respuestaClickEnlace , true);
function respuestaClickCapa(evt: Event): void { evt.stopImmediatePropagation();
}
function respuestaClickCapa2(evt: Event): void { }
function respuestaClickEnlace(evt: Event): void {
// No se ejecuta
}

Hemos registrado dos handlers para el mismo evento en el mismo elemento, capa. Como
vimos antes, los handlers se ejecutan en el orden en el que se registraron por lo que al hacer click en
boton se ejecutar primero respuestaClickCapa(). En esa funcin hemos invocado el mtodo
stopInmediatePropagation() del objeto del tipo Event que ha entrado por parmetro. Eso no evita que
el evento se siga propagando hacia los dems elementos visuales, sino que se consigue que los otros
handlers registrados del mismo evento para el mismo elemento no se ejecuten. En este ejemplo no se
ejecutara respuestaClickCapa2().

17.3

Eventos no visuales

Dada la naturaleza de la propagacin de eventos, los no visuales slo tienen una fase, la de
objetivo. No es posible recorrer una jerarqua visual si sta es inexistente.
Un ejemplo claro de este tipo son los eventos que disparan los objetos de la clase
XMLHttpRequest (Ajax).
El registrar un handler estableciendo el capture a true en el mtodo addEventListener no
supone ninguna diferencia.

244

18. Ajax
18.1

Introduccin

AJAX, Asynchronous JavaScript And XML (JavaScript asncrono y XML) es en una tcnica
de desarrollo web que nos permite llamadas al servidor de una forma asncrona, es decir, podemos
seguir utilizando la aplicacin mientras sta procesa la peticin en segundo plano.
Para utilizar esta tcnica debemos recurrir a la clase XMLHttpRequest. sta nos provee de los
mtodos necesarios para interactuar con el servidor.

18.2

Clase de utilidad

En este tema vamos a hacer una sencilla clase llamada Ajax para manejar las peticiones de
una forma ms verstil.
Como hemos dicho es imprescindible usar la clase XMLHttpRequest para realizar peticiones
al servidor.
class Ajax {
private xmlR: XMLHttpRequest;
}

Los mtodos de interaccin los vamos a hacer estticos para evitar instanciar la clase Ajax de
forma manual cada vez que queramos usarla.
class Ajax {
private xmlR: XMLHttpRequest;
private success: (data: any) => void;
private static init = (): Ajax => {
var ajax: Ajax = new Ajax();
ajax.xmlR = new XMLHttpRequest();
ajax.xmlR.addEventListener("readystatechange",
ajax.onReadyState, true);
return ajax;
}
}

En
el
mtodo
instanciamos
la
clase
Ajax.
Inicializamos el atributo privado xmlR. Aunque sea privado es accesible porque estamos dentro de la
246

clase.
Registramos el listenener con el evento readystatechange que es el que se lanza cuando hay alguna
noticia de la comunicacin. El handler utilizado es onReadyState que veremos despus.
Ajax tiene dos formas de comunicarse con el servidor: post y get. Normalmente se utiliza
post por ser ms seguro. El servidor recibira los datos por get en forma de parmetros en la url.
Vamos a hacer slo el Post para simplicar el tema.
public static post = (url: string, success?: (data: any) => void): void => {
var ajax: Ajax = Ajax.init();
ajax.success = success;
ajax.xmlR.open("post", url, false);
}

Es esttico pblico para que el programador pueda usarlo sin problemas. Por parmetro
tenemos:
La url hacia donde se har la peticin y la fuuncin de nombre success que se ejecutar si
todo ha ido bien, la cual se guarda en la instancia.
En el cuerpo del mtodo se instancia la clase Ajax a travs de init()
Asignamos la funcin success al atributo de la instancia. Abrimos la comunicacin con el servidor.
Para controlar la comunicacin nos falta el mtodo onReadyState()
private onReadyState = (evt: Event) => {
var xmlR: XMLHttpRequest = this.xmlR;
switch (xmlR.readyState) {
case 4:
if (xmlR.status == 200) {
this.success(xmlR.responseXML);
}
else if (xmlR.status == 404) { }
else if (xmlR.status == 500) { }
break;
}
}

Recuperamos el objeto XMLHttpRequest que hemos usado para la peticin. Cabe decir que
este mtodo va a ejecutarse varias veces en todo el proceso pues se lanzarn varios eventos distintos.
Por ello hemos hecho un switch con xmlR.readyState que es donde se almacena el estado de la
peticin. En 4 indica que ya ha sido procesado aunque debemos inspeccionar el valor de xmlR.status.
200 es el indicador de que todo ha ido bien. Si es as procedemos a ejecutar la funcin success
pasndole como argumento los datos obtenidos los cuales hemos supuesto que son XML. Si es texto
plano o JSON se hara con xmlR.responseText.
Esta clase es muy mejorable. Por ejemplo, usando enums para el readyState, creando el
mtodo para peticiones get, etc. Dejo en tus manos el mejorarla con los conocimientos que has
adquirido.

248

18.3

Estados de la peticin y respuesta del servidor


readyState

status

Cdigo
0
1
2
3
4

Significado
Peticin no iniciada
Conexin establecida
Peticin recibida
Procesando peticin
Peticin finalizada y respuesta lista
Cdigo
200
404

250

Significado
Correcto
No encontrado

252

19. Mdulos
19.1

Introduccin

Nuestra aplicacin puede ir creciendo de forma que se haga necesario el trabajar con paquetes
de clases para ordenar de una forma efectiva nuestro trabajo.A estos paquetes se les llaman mdulos.
En ellos colocamos nuestras clases, interfaces, funciones e incluso variables. La idea es
agruparlas por funcionalidad.
Para crear uno basta con encerrar el cdigo que queramos en un bloque module:
module M {
// Cdigo
}

Aadimos nuestras clases o interfaces normalmente. Para que sean accesibles desde fuera del
mdulo necesitamos declararlas como export.
module M {
export class A { }
}

Para acceder a ella basta con escribir el nombre del mdulo seguido del nombre de la clase.
var a: M.A = new M.A();

Tambin pueden contener variables ya inicializadas o no.


module M {
export class A { }
export var a: number = 1;
}

Se puede declarar una ruta completa para un mdulo de la forma:


module M.A.B {
export class A { }
}

Y para acceder a la clase A habra que escribir: M.A.B.A

254

19.2

Partes de un mdulo

Cuando hacemos referencia al mdulo a travs de su nombre original, en este caso M,


estamos accediendo a la parte de las interfaces, la no instanciada. Pero si accedemos a travs de una
variable del tipo del mdulo, estamos accediendo a la parte instanciadas que comprende las
variables, clases, enumerados y funciones. Realmente un mdulo es un objeto de JS. Recordemos
que las interfaces en TS no tienen equivalencia en JS, por lo que cuando declaramos una no genera
cdigo. Si un mdulo slo tiene interfaces, ese mdulo no tiene equivalencia en JS de ninguna
forma, por ello no es posible acceder a la parte instanciada, pues sta slo se crea cuando realmente
se genera cdigo JS.
module M {
export class A { }
export interface B { }
export var a: number = 1;
}
var m: typeof M = M; /* Ahora con m podemos acceder a las entidades que no
sean interfaces */
m.a = 2 // Correcto
m.A // Correcto
m.B // Error. Es una interfaz.
var f: M.B; // Correcto.

19.3

Importar tipos

Podemos importar mdulos y sus entidades a otros mdulos con la palabra reservada import
para un manejo ms fcil de los mismos.
module A{
export class Persona { }
}
module B {
import Persona = A.Persona;
var carlos: Persona;
var jose: A.Persona;
}

Tenemos dos mdulos independientes, cada uno con sus entidades.


En el mdulo A tenemos una class llamada Persona. En el mdulo B tenemos un import
llamado Persona que en realidad es un alias a la clase Persona del mdulo A. Al establecerle el
mismo nombre en el import, manejamos la clase como si estuviera dentro del mdulo B, ahorrdonos
tener que escribir toda su ruta hasta llegar a ella. La variable jose es del mismo tipo que carlos.
Hay una regla a la hora de exportar miembros: si un miembro exportado hace uso de alguna
clase, interfaz o enum en su mismo nivel, tambin deben ser exportadas o fallar.
256

module A {
interface B() { }
export function ejemplo(b: B): void { }
}

La compilacin falla porque la funcin ejemplo que est exportada usa la interfaz B que no lo
est. Es obligatorio exportar B tambin.

19.4

Un mismo mdulo en distintos archivos

Una caracterstica importante de los mdulos es la posibilidad de declarar el mismo en


archivos distintos.
moduloA1.ts
module A{
export class Persona { }
}

moduloA2.ts
module A{
export class Alumno extends Persona { }
}

Tenemos dos archivos distintos: moduloA1.ts y moduloA2.ts. En ambos se declara del


mdulo A. En moduloA1 tenemos una clase de nombre Persona y en moduloA2.ts tenemos una clase
de nombre Alumno que hereda de Persona. Al estar en el mismo mdulo, no hay problemas. Pero al
estar en archivos separados moduloA2.ts no sabe dnde buscar la clase Persona. Para ello hay que
hacer referencia a ese archivo de forma explcita
moduloA2.ts
/// <reference path="moduloA1.ts" />
module A {
export class Alumno implements Persona { }
}

Se ha hecho referencia al archivo moduloA1.ts a travs de su ruta relativa. De esta forma ya


tiene acceso a Persona.

19.5

Fusionando mdulos con funciones y enums

Es una posibilidad muy interesante que nos permite TS por la podemos aadir atributos a las
funciones o mtodos a los enums.

258

19.5.1

Funciones

function fusion():void{
alert("fusin");
}
module fusion {
export var fusion: number = 1;
}

Primero se declara la funcin y despus el mdulo a fusionar con el mismo nombre. De esta
forma tenemos acceso a lo exportado en el mdulo desde el nombre de la funcin. Incluso podemos
usarlo dentro de la propia funcin.
function fusion():void {
funsion.fusion;
}
module fusion {
export var fusion: number = 1;
}

19.5.2

Enums
De la misma forma que se fusionan las funciones y los mdulos lo hacen los enums.

enum Direcciones { Izquierda, Derecha, Arriba, Abajo }


module Direcciones {
export function diagonal(c1: Direcciones) {
// Cdigo
}
}
Direcciones.diagonal(Direcciones.Izquierda);

19.6

Mdulos externos (node.js y require.js)

Podemos importar mdulos externos con la palabra reservada require:


import module = require("modulo");

Para ello los mdulos deben estar separados en archivos pero sin usar la estructura module.
Persona.ts
export class Persona() { }

260

app.ts
import Persona = require("./Persona");
var persona:Persona.Persona = new Persona.Persona();

Tan sencillo como escribir ./ seguido del nombre del archivo a importar. En este caso se
importara todo Persona.ts. Para hacerlo ms sencillo podemos usar Export= en los archivos que
representan mdulos. Slo tiene sentido si estos slo tienen un miembro que exportar.
Persona.ts
class Persona { }
export = Persona;

app.ts
import Persona = require("./Persona");
var persona: Persona = new Persona();

As podemos importar directamente con el nombre del fichero y, al instanciarla, nos evitamos
la incomodidad de escribir toda la ruta cualificada.
En el caso de usarlos debemos especificarlo como parmetros del compilador:
Para Node.js
--target commonjs
Para require.js
--target amd

19.7

Trabajando con libreras externas

Una de las grandes ventajas de TS es su compatibilidad con libreras escritas en JS. No es


necesario reescribirlas en TS para que podamos usar sus ventajas.
Para tipar una librera externa se debe generar un archivo de definiciones que nos provea de
las entidades para ser consumidas.
Estos archivos se usan en el caso de trabajar con la librera directamente en JS. Este archivo
trabaja como una interfaz en la que se nos presenta las funcionalidades y posibilidades de la librera
y se nos da la posibilidad de interactuar con ella.
En este sentido se est llevando a cabo un excelente trabajo de la comunidad para crear
achivos de definiciones de cientos de libreras. Es de cdigo libre y est alojado en Github.
https://github.com/borisyankov/DefinitelyTyped

262

En l podemos encontrar definiciones para libreras tan conocidas como jQuery, AngularJS
etc.
Cuando creamos nuestra aplicacin directamente en TS, el compilador genera un archivo de
definiciones de forma automtica pero esta funcionalidad es experimental y contiene an bastantes
bugs por resolver.

19.7.1

Archivos de definiciones
Nosotros podemos crear nuestros propios archivos de definiciones de forma manual.

Bsicamente lo que se hace es escribir en un archivo de extensin .d.ts todas nuestras clases,
interfaces, enums, funciones, mdulos y variables que queremos publicar para que puedan ser
usados.
Para ello se utiliza la palabra reservada declare seguido de la entidad que sea: clase, enum,
funcin, mdulo o variable pero sin implementar, es decir, no se reescribe el cuerpo slo su cabecera.
Con las interfaces no es necesario.
declare class Persona {
constructor(private edad: number);
}

As podremos usar Persona en nuestra aplicacin TS para instanciarla, extenderla, etc.

19.8

Evitar que una clase pueda ser superclase

Podemos hacer que una clase no pueda ser usada para herencia descomponindola en dos
interfaces.
interface Persona_Estatica {
edad(edad: number): Persona_Instancia;
}
interface Persona_Instancia {
edad: number;
}
declare var Persona: Persona_Estatica;

Recordamos que una clase tiene dos partes: la de instancia y la esttica. Se declaran dos
interfaces, una por cada parte de la clase. El constructor, que recordemos es de la parte esttica,
devuelve un objeto del tipo de la parte de instancia. Si te fijas, la variable tiene el nombre que
debera tener la clase, A, y es del tipo de la parte esttica de la clase, por lo que contendr el
constructor y todos los dems miembros estticos. Con ello podemos hacer
var carlos = new Persona("Carlo");

Como new Persona(); devuelve el tipo Persona_Instancia, tenemos disponibles sus miembros
no estticos.
264

As evitamos que se puedan crear clases heredadas de nuestra clase Persona original pues una
clase no puede tener como superclase una interfaz.
Cabe recordar que esto es slo posible cuando estamos escribiendo archivos de definicin
pues la implementacin del cdigo ya est escrita en el .js que hemos cargado mediante el tag script
de html.

266

268

20. Anexo I. Arrays


20.1

Introduccin

En TS un array es en realidad una lista de elementos. Como se ve en la imagen se puede


representar como espacios contiguos donde se almacenan valores. Es conveniente tipar de forma que
sepamos de qu tipo son los valores que contiene.
Cada elemento del array tiene asignado un ndice numrico el cual nos permite acceder al
valor. En TS empiezan por 0. Si conocemos el ndice slo tenemos que escribir el nombre del array y
entre corchetes el ndice numrico:
var elementos: Array<string> = []; // Vaco
elementos [2]; // undefined

Si tenemos que recorrer todos los elementos para encontrar algo o, simplemente, para hacer
algo con todos ellos necesitamos los bucles. Con el bucle for podemos recorrer el array en el orden
que queramos.
Desde el principio:
for (var i: number = 0; i < elementos.length; i++) { }

Podemos tambin recorrer el array empezando por el final:


for (var i: number = elementos.length - 1; i > 0; i--) { }

El ndice inicial es el tamao del array menos uno porque recordemos el ndice empieza por
0. Si tenemos 5 elementos en un array, el quinto tendr de ndice 4.
La clase Array tiene mtodos y atributos muy tiles para trabajar con ellos.

270

20.2
20.2.1

Atributos
Length

Almacena el tamao del array.


var elementos = [undefined, "gg", undefined, null];
elementos.length // 4

20.3

Mtodos

El array que usaremos para algunos ejemplos es el siguiente:


var numeros = [1,2,3];

20.3.1

concat
Combina dos o ms arrays.

var numeros2 = [4, 5, 6];


var numeros3 = numeros.concat(numeros2);
// numeros3 es [1,2,3,4,5,6]

20.3.2

every
Comprueba si todos los elementos del array satisfacen una funcin pasada como argumento.

Funcin como argumento:


(value:T, index:number, array: T[]) => Boolean
function comprobarSiSon2(valor:number, index:number, array:number[]):boolean{
var test:boolean = false;
if (valor == 2){
test = true;
}
return test;
}
numeros.every(comprobarSiSon2); // false

La funcin comprueba si todos los elementos del array son el nmero 2. Como no es as,
devuelve false.

20.3.3

some
272

Comprueba si al menos uno de los elementos del array satisface una funcin pasada como
argumento.
Funcin como argumento:
(value:T, index:number, array: T[]) => boolean
function comprobarSiAlgunoEs2(valor:number, index:number,
array:number[]):boolean{
var test:boolean = false;
if (valor == 2){
test = true;
}
return test;
}
numeros.some(comprobarSiAlgunoEs2); // true

La funcin comprueba si al menos uno de los elementos del array es el nmero 2. Como uno
lo es, devuelve true.

20.3.4

filter
Devuelve un array filtrando los elementos segn una funcin pasada como argumento.

Funcin como argumento:


(valor:T, index:number, array:T[]) => boolean
function filtrarSolo2(valor:number, index:number, array:number[]):boolean{
var filt:boolean = false;
if (valor == 2){
filt = true;
}
return filt;
}
var arrayFiltrado = numeros.filter(filtrarSolo2);
// arrayFiltrado es [2]

La funcin slo da por bueno aquellos elementos que sean el nmero 2 descartando los que
no lo sean.

20.3.5

foreach
Recorre todos los elementos del array aplicndoles la funcin pasada como argumento
274

Funcin como argumento:


(valor:number, index:number, array:number[]) => void
function recorrer(valor:number, index:number, array:number[]):void{
array[index] = valor + 1;
}
array.forEach(recorrer);

La funcin suma 1 a todos los elementos del array. Si modificamos el parmetro valor, no
surtira efecto en el array pues los tipos primitivos se pasan por valor y no por referencia.
function recorrer(valor:number, index:number, array:number[]):void{
++valor;
}
numeros.forEach(recorrer); // array es [1,2,3]

Pero si lo usramos con objetos:


var array = [new Persona(18), new Persona(60)];
function cambiarEdad(valor:Persona, index:number, array:Persona[]):void{
valor.setEdad( valor.getEdad()+1 );
}
numeros.forEach(cambiarEdad); /* array contiene 2 personas. Una con 19 aos y
otra con 61. */

No sera necesario acceder al valor a travs del array y su ndice.

20.3.6

indexOf

Recorre el array buscando el elemento pasado como argumento, devolviendo el ndice de la


primera ocurrencia. Devuelve -1 si no lo encuentra
var indice:number = numeros.indexOf(2); // 1

Tambin se puede invocar el mtodo con un argumento opcional que especfica a partir de
qu posicin debe empezar a buscar.
var indice:number = numeros.indexOf (2, 2); // -1

20.3.7

lastIndexOf

Recorre el array buscando el elemento pasado como argumento, devolviendo el ndice de la


ltima ocurrencia. Si no lo encuentra devuelve -1
var indice:number = numeros.indexOf (2); // 1

276

Tambin se puede invocar el mtodo con un argumento opcional que especfica a partir de
qu ndice debe empezar a buscar.
var indice:number = numeros.indexOf (2, 2); // -1

20.3.8

join

Devuelve el array como un string donde sus elementos estn separados por un carcter
pasado como argumento.
var arrayComoString:string = numeros.join("-");
// 1,2,3

Hemos convertido el array en un string separado por guiones. Ejecuta el mtodo toString() de
cada elemento del array.

20.3.9

map

Recorre todos los elementos del array ejecutando el cdigo de la funcin pasada como
argumento a cada uno de ellos y devuelve un array con los cambios realizados sin modificar el array
original.
function map(valor:number, index:number, array:number[]):number{
return ++valor;
}
var numeros2 = numeros.map(map);

El array numeros sigue siendo [1,2,3] pero numeros2 es [2,3,4] puesto que hemos sumado
uno a cada elemento.

20.3.10 shift
Elimina el primer elemento del array y lo devuelve
var primerElemento = numeros.shift();
// primerElemento es 1

20.3.11 pop
Elimina el ltimo elemento del array y lo devuelve
var ultimoElemento = numeros.pop();
// ultimoElemento es 3

20.3.12 push
278

Aade un nuevo elemento al final del array y devuelve el tamao del array.
var nuevoTamano:number = numeros.push(8);
// nuevoTamano es 4

20.3.13 unshift
Inserta nuevos elemento al principio del array y devuelve el nuevo tamao del array.
var nuevoTamano:number = numeros.unshift(8);
//array es [8,1,2,3]

20.3.14 reduce
Aplica una funcin simultneamente a dos valores de un array (de izquierda a derecha) .
Funcin como argumento:
(valorPrevio:T, valorActual:T, ndice:index, array:T[]) => T
function reduce(valorPrevio:number, valorActual:number, ndice:number,
array:number[]):number{
return valorPrevio + valorActual;
}
var sumaArray:number = numeros.reduce(reduce);

De esta forma el valor previo es el primer elemento del array y el valor actual el segundo.
Primera iteracin:
valorPrevio = 1, valorActual = 2. Resultado: 3
Segunda iteracin
valorPrevio: 3 (es el resultado de la iteracin anterior), valor actual = 3. Resultado: 6
Si se inserta un segundo argumento a reduce, ese argumento sera el valorPrevio en la
primera iteracin y el valorActual sera el primer elemento del array
var sumaArray:number = array.reduce(reduce,50);

Primera iteracin:
valorPrevio = 50, valorActual = 1. Resultado: 51
Segunda iteracin
valorPrevio: 51 (es el resultado de la iteracin anterior), valor actual = 2. Resultado: 53
Tercera iteracin
valorPrevio: 53 (es el resultado de la iteracin anterior), valor actual = 3. Resultado: 56
280

20.3.15 reduceright
Aplica una funcin simultneamente a dos valores de un array (de derecha a izquierda) para
reducirlo a un nico valor.
Definicin del mtodo:
(valorPrevio:T, valorActual:T, ndice:number, array:T[]) => T
function reduceRight(valorPrevio:number, valorActual:number, ndice:number,
array:number[]):number{
return valorPrevio + valorActual;
}
var sumaArray:number = numeros.reduceRight(reduceRight);

De esta forma el valor previo es el ltimo elemento del array y el valor actual el penltimo.
Primera iteracin:
valorPrevio = 3, valorActual = 2. Resultado: 3
Segunda iteracin:
valorPrevio: 3 (es el resultado de la iteracin anterior), valor actual = 1. Resultado: 6
Si se inserta un segundo argumento a reduceRight, ese argumento sera el valorPrevio en la
primera iteracin y el valorActual sera el ltimo elemento del array
var sumaArray:number = numeros.reduceRight(reduceRight,50);

Primera iteracin:
valorPrevio = 50, valorActual = 1. Resultado: 51
Segunda iteracin:
valorPrevio: 51 (es el resultado de la iteracin anterior), valor actual = 2. Resultado: 53
Tercera iteracin:
valorPrevio: 53 (es el resultado de la iteracin anterior), valor actual = 3. Resultado: 56

20.3.16 reverse
Devuelve el array original dndole la vuelta al orden de sus elementos.
var arrayReverse = numeros.reverse();
// arrayReverse es [3,2,1];

20.3.17 slice
282

Devuelve un trozo del array estableciendo como argumentos los ndices de principio y fin,
ambos opcionales. Si no se establece ninguno, hace una copia completa del array.
var trozoArray = numeros.slice(1);
// trozoArray es [2,3]

20.3.18 sort
Ordena un array mediante el criterio dado por una funcin. Si se omite la funcin sern
ordenados de forma ascendente mediante caracteres ASCII.
var array = [4,7,1,3,9,6];
array.sort();
// array es [1,3,4,6,7,9]

Funcin como argumento: (a:T, b:T) => number


La funcin debe devolver un nmero:
0 = si los elementos son iguales
1 = si el primer elemento parametrizado es mayor al segundo
-1 = si el primer elemento parametrizado es menor al segundo.
Con esto obtendramos un orden ascendente. Si queremos un orden descendente slo
debemos cambiar el 1 por el -1, y el -1 por el.
function ordenarDescendente(n1: number, n2: number): number {
var orden: number = 0;
if (n1 > n2) {
orden = 1;
} else if (n1 < n2) {
orden = -1
}
return orden;
}
numeros.sort(ordenarDescendente);
// numeros es [9,7,6,4,3,1]

20.3.19 splice
Elimina elementos del array pudiendo sustituirlos por otros. Devuelve un array con los
elementos eliminados.
var eliminados = numeros.splice(0,1); /* Empieza en el 0 y avanza uno.
eliminados es [1] */
var eliminados = array.splice(0,1, 9); /* Empieza en el 0 y avanza uno e inserta 9
en su lugar. eliminados es [1] array es [9,2,3] */

284

20.3.20 toString
Devuelve el Array en forma de cadena de caracteres separados por coma. Ejecuta el mtodo
toString() de cada objeto si lo posee.
class Persona{
constructor(private nombre:string){}
return this.nombre;
}
}

toString():string{

var array:Array<Persona> = [new Persona("Jos"),new Persona("Carlos")];


array.toString() // "Jos, Carlos"

Si no poseyera el mtodo toString(), devolvera [object Object]


class Persona{
constructor(private nombre:string){}
}
var array:Array<Persona> = [new Persona("Jos"),new Persona("Carlos")];
array.toString() // [object Object],[object Object]

Esto ocurre porque no sabra cmo convertir las instancias de esa clase en un String. Los
tipos primitivos y envoltura poseen el mtodo toString().

286

288

21. Anexo II Strings


Los strings no son ms que cadenas de caracteres. Un carcter puede ser cualquier cosa: letra,
nmero, smbolo, etc, encerrado entre comillas simples o comillas dobles.
Para hacernos ms fcil el manejo de los mismos, TS nos provee mtodos de String muy
tiles de la misma forma que lo hace JS.

21.1
21.1.1

Atributos
length

El tamao del string medido en el nmero de caracteres.


var nombre:string = "Jos Carlos";
var tamanoNombre:number = nombre.length;
/* tamanoNombre es 11 porque los espacios en blanco tambin cuentan */

21.2

Mtodos

El string que usaremos para algunos ejemplos es el siguiente:


var nombre:string = "Jos Carlos";

21.2.1

charAt
Devuelve el carcter de la posicin numrica pasada como argumento.

var caracter3:string = nombre.charAt(3);


//caracter3 es ""

21.2.2

charCodeAt
Devuelve el cdido ASCII del carcter de la posicin numrica pasada como argumento.

var caracter3:number = nombre.charCodeAt(3);


//caracter3 es 233

21.2.3

concat
290

Devuelve un string que es la concatenacin de dos o ms.


var apellidos:string = "Lama Ponce";
var nombreCompleto:string = nombre.concat(apellidos);
// nombreCompleto es "Jos Carlos Lama Ponce"

21.2.4

indexOf

Devuelve la posicin de la primera ocurrencia del string suministrado como argumento.


Devuelve -1 si no lo encuentra.
var posicionPrimeraS:number = nombre.indexOf("s");
// posicionPrimeraS es 2

Si se le proporciona una cadena y no un solo carcter, buscar la coincidencia de la cadena al


completo pero devolver la posicin del primer carcter
var posicionCar:number = nombre.indexOf ("Car");
//posicionCar es 5

21.2.5

lastIndexOf

Devuelve la posicin de la ltima ocurrencia del string suministrado como argumento.


Devuelve -1 si no lo encuentra.
var posicionUltimaS:number = nombre.lastIndexOf("s");
// posicionUltimaS es 10

Si se le proporciona una cadena y no un solo carcter, buscar la coincidencia de la cadena al


completo pero devolver la posicin del primer carcter.
var posicionCar:number = nombre.indexOf ("Car");
//posicionCar es 5

21.2.6

match

Busca en una cadena una expresin regular u otra cadena. Si la encuentra devuelve las
ocurrencias en forma de array.
var resultado = nombre.match(/o/g); /* Devuelve un array de 2 posiciones */
var resultado = nombre.match("o"); /* Devuelve un array de 1 posicion */

Si la bsqueda se hace con otra cadena, slo devuelve la primera ocurrencia encontrada
empezando por la izquierda.

21.2.7

replace
292

Encuentra coincidencias en la cadena a partir de una expresin regular u otra cadena para
sustituirlas las ocurrencias por una nueva cadena
var nombreReal = nombre.replace("e","")); // Jos Carlos
var nombre:string = "J o se C ar l o s";
var nombreReal = nombre.replace(/\s/g,"")); // Jos Carlos. Elimina los espacios

21.2.8

search

Busca en la cadena la cadena o expresin rgular introducida como argumento y devuelve el


ndide de la primera ocurrencia de izquierda de derecha. Si no la cuentra devuelve null.
var letraJ = nombre.search("J") // 1

21.2.9

slice

Devuelve un trozo del string proporcionando los ndices como argumento. El primero
determina donde empieza. El segundo donde acaba sin incluirlo.
var primeroNombre:string = nombre.slice(0,2);
// primeroNombre es "Jo"

Puede empezar por el final si se proporciona el segundo argumento negativo.


var primeroNombre:string = nombre.slice(0,-2);
// primeroNombre es "Jos Carl"

Si el ndice de comienzo es negativo, comienza por el ndice calculado de la longitud de la


cadena + ndice de comienzo
var primeroNombre:string = nombre.slice(-5,7);
// primeroNombre es a
/* El ndice de comienzo es -5. Sumamos la longitud que es 11 y resultara 6.
Es equivalente a nombre.slice(6,7); */

21.2.10 split
Convierte el string en un array de strings proporcionando como paremtro el carcter
separador.
var nombresSeparados:string[] = nombre.split(" ");
// nombresSeparados es ["Jos","Carlos]

Hemos roto el string por el espacio en blanco.


294

21.2.11 substr
Devuelve un trozo del string proporcionando como argumento el ncide de incio y la longitud.
Si la longitud es 0 o negativa, se devuelve una cadena vaca. Si no se proporciona, avanza hacia el
final de la cadena.
var primeroNombre:string = nombre.slice(0,-2);
// primeroNombre es "Jo"

21.2.12 substring
Devuelve un trozo del string proporcionando los ndices como argumento. El primero
determina donde empieza. El segundo donde acaba sin incluirlo. Si el ndice de terminacin es
menor al de comienzo, se intercambian.
nombre.slice(0,4) es quivalente a nombre.slice(4,0);
var primeroNombre:string = nombre.slice(0,4);
// primeroNombre es Jos

21.2.13 toLowerCase
Convierte todos los caracteres en minsculas.
var nombreMinusculas:string = nombre.toLowerCase();
// nombreMinusculas es "jos carlos"

21.2.14 toUpperCase
Convierte todos los caracteres en maysculas
var nombreMayusculas:string = nombre.toUpperCase();
// nombreMayusculas es "JOS CARLOS"

21.2.15 trim
Elimina los espacios en blanco del principio y final del string.
var nombre:string = "
Jos Carlos
var nombreSinEspacios:string = nombre.trim();
// nombreSinEspacios es "Jos Carlos"

296

";

298

22. Anexo III. JSON


JSON, acrnimo de JavaScript Object Notation, es un formato ligero para el intercambio de
datos. JSON es un subconjunto de la notacin literal de objetos de JavaScript que no requiere el uso
de XML.
JSON es realmente un Object de Javascript, lo que podemos representar por {}. Un ejemplo
de JSON sera el siguiente.
{"productos": {
"camaras": [
{"modeloA": {"precio":"100"} },
{"modeloB": {"precio":"200"} }
],
"relojes": [
{"relojA": {"precio":"100"} },
{"relojB": {"precio":"200"} }
]
}
}

JSON se compone de, bsicamente, seis tipos de datos: {}, Array, String, Number, Null y
Boolean. Lo normal es que todo el archivo se agrupe en un {} de modo que tenga toda la
informacin accesibles a travs de ndices de cadenas de caracteres. Si quedemos agrupar {}
relacionados usamos los Arrays mediante literales [].
En el ejemplo tenemos un objeto con un ndice llamado productos. ste, a su vez, es un {}
con otros dos ndices: camaras y relojes. Estos son arrays que contienen cada uno {} que representan
los distintos productos ya detallados, en este caso con el precio de cada uno.
Los ndices pueden ser strings o booleanos aunque no es necesario encerrarlo entre comillas.

22.1
22.1.1

La clase JSON
De JSON a JS

Es til cuando trabajamos con Ajax y recibimos la respuesta del servidor en JSON. sta no es
reconocible directamente por JS pues es una cadena de caracteres. Para convertir esa cadena en una
estructura de datos real debemos usar JSON.parse()
Es un mtodo esttico al que se le pasa como argumento el string que queremos convertir
para poder trabajar con los datos.

300

JSON.parse('{}');
// {}
JSON.parse('false');
// false
JSON.parse('"algo"');
// "algo"
JSON.parse('[10, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null');
// null

22.1.2

De JS a JSON

Si queremos enviar datos en formato JSON al servidor o a cualquier otra aplicacin que los
acepte, debemos convertir nuestra estructura en un string que est bien formado para que la otra
parte pueda reconocerlo sin problemas. JSON.stringify()
JSON.stringify({});// '{}'
JSON.stringify(true); // 'true'
JSON.stringify("cadena"); // '"cadena"'
JSON.stringify([1, "false", false]); // [1,"false",false]'
JSON.stringify({ x: 5 }); // '{"x":5}'

Ambas poseen un segundo parmetro del tipo function que es opcional y su definicin es la
siguiente:
(key:any, value:any) => any
La funcin tiene como parmetros el ndice y el valor de ese ndice. Y debe devolver algo. Lo
que hace es sustituir el valor correspondiente por uno que queramos.
var productos:string; // Es el JSON de ejemplo de este anexo.
function sustituir(key:string, value:any): any{
if (key == "modeloA"){
return 200;
}else {
return value;
}
}
var datosProductos = JSON.parse(productos, sustituir);

Hemos sustituido el precio del modeloA a 200.

302

Potrebbero piacerti anche