This graph shows how many times the word ______ has been mentioned throughout the history of the program.
¿Qué vamos a ver en la clase de hoy del FullStack Bootcamp?
Pues vamos a ver cómo realizar una API desde cero con Express y Node junto con TypeScript.
Vamos a hacerla desde cero y vamos a ver poco a poco cómo le vamos a añadir los tipos,
cómo funciona, qué problemas podemos encontrar, configurar el linter,
vamos a ver también cómo tener un entorno de desarrollo de nuestra API con TypeScript,
con funcionaria, todo esto, y vamos a ver cómo va evolucionando.
Así que vamos a empezar desde lo más sencillo de inicializar el proyecto y todo esto,
y conforme encontremos algún tipo de reto, pues veremos cómo lo solucionamos.
Vamos a empezar desde cero, o sea, vamos a crear el proyecto todo.
Vale, pues vamos a empezar nuestra aplicación.
A ver dónde estoy aquí, vale, estoy aquí en mi carpeta.
Vamos a crear una carpeta que le voy a llamar Express TypeScript.
No sé si lo veis, voy a hacer un poquito más grande, ¿vale?
Y vamos a hacerla más pequeña para que lo veáis.
Express TypeScript.
Entramos a Express TypeScript, npm init, guión y, para que se inicialice con todo por defecto.
Y, por supuesto, ya te he dicho que vamos a utilizar TypeScript.
Por lo tanto, npm install, TypeScript, guión d, ¿vale?
Porque es una guión mayúscula d, es porque es una dependencia de desarrollo.
Y esto nos lo va a dejar en el Package JSON en las dependencias de desarrollo.
Con esto ya hemos inicializado nuestro proyecto.
Pues vamos a ver qué tenemos que hacer.
Vamos a ver.
Vamos a iniciar nuestro Visual Studio Code.
Y ya en el Package JSON, lo primero que voy a hacer es añadir un script que le llamará
TCC de TypeScript.
Y vamos a ejecutar el binario de TCC.
Este TCC, al final, lo que hace es transformar los ficheros de TypeScript a JavaScript para
que los pueda leer y ejecutar, tanto navegador como Node, como cualquier cosita.
Vale.
Ahora que tenemos esto, pues venga, vamos a empezar.
¿Qué podríamos hacer?
Bueno, inicializar primero nuestro proyecto de TypeScript, ¿vale?
Así que, npm run TCC, porque es el script que acabo de crear aquí en el Package JSON.
Y ahora pongo guión, guión, guión, guión init.
¿Y esto qué es?
Pero, Midu, ¿qué cosas más raras haces?
Vale, a ver, esto del guión, guión, es porque si no pongo guión, guión, lo que va a pasar
aquí es que estos parámetros que yo paso a este init, le llegaría al comando npm run.
Y hay que poner este guión, guión, para que el parámetro este de init no le llegue
al npm run, sino que le llegue al TCC este de aquí.
O sea, que por eso se utiliza.
Lo digo por si alguna vez lo veis, que sepáis cuál es la explicación de esto.
Inicializamos nuestro proyecto y ya tenemos aquí un tsconfig.json.
Esto no siempre es obligatorio, pero es recomendable porque tienes un montón de configuración.
Yo te voy a explicar un poquito la que vamos a ir activando, por qué la vamos a ir activando
y todo eso.
Te recomiendo un montón que lo hagas así porque además ves que tienes aquí todos los comentarios
que te explica para qué es cada cosa.
Por ejemplo, el target que tenemos aquí en Macri 5, pues lo podemos cambiar a en Macri 2015
por poner uno.
Módulos.
Vamos a utilizar CommonJS.
Esto es cómo lo va a expulsar el código.
O sea, tú puedes seguir utilizando módulos en tu código, pero luego cuando lo compile,
veremos que lo están poniendo en el módulo este de CommonJS.
CommonJS, si no lo sabes, es el tema de los requires, ¿vale?
En Macri Modules sería imports y todo esto, CommonJS sería require, bla, bla, bla.
Así que módulo, CommonJS.
¿Qué más tendríamos que...?
Bueno, podríamos cambiar el outdir, ¿vale?
Aquí ves que tenemos outdir.
Esto sería la carpeta donde va a dejar los archivos compilados TypeScript.
Pues vamos a cambiarlo y le vamos a poner barra build.
¿Qué más?
¿Qué más podríamos poner?
Algún check que haya por aquí.
El streak.
Este está bien porque tienes un montón.
Todo esto, ves que pone streak, streak, streak.
Son un montón de chequeos estrictos, digamos, para tu código y está por true, por defecto.
Pues lo vamos a dejar así, aunque a veces es un poco problemático porque, claro, cuanto más estricto, pues más difícil es.
Pero bueno, no pasa nada.
Vamos a también descomentar estas.
The no unuslocals, que esto te dice si tienes algún parámetro, bueno, alguna variable local sin utilizar.
Esto a veces lo hace el linter, pero en este caso también TypeScript tiene este tipo de control para que te dé un error.
Parámetros que no utilizamos y no implicit returns, ¿vale?
Este, bueno, este creo que lo veremos a lo largo de la clase, como nos va a dar un error por no utilizarlo.
O sea, por ponerlo en true, veremos en un momento que tendríamos que poner un return.
Si no, lo podríamos haber dejado pasar.
O sea, siempre nuestras funciones tienen que tener un return.
¿Qué significa?
Que si tienes un undefined, por ejemplo, pues deberías poner un return.
Porque undefined es lo que devuelve una función por defecto.
Y en este caso dice, no, no, tienes que poner tú a mano.
Luego también está este.
Este también es interesante.
Este me gusta bastante, que es para los switch, para que tengas que poner en todos un return.
Esto lo que te hará es que no tengas que poner, o sea, cada vez que tengas un switch case, pues tengas que tener un return.
Para evitar que caiga un break.
Para evitar que caiga uno, debe caer.
¿Vale?
¿Qué más?
En advance, creo que hay unos cuantos.
Bueno, este es interesante también para que funcione tanto Smart Grid Modules como Common GS.
Y en advance tenemos skip, lift, check.
Este lo vamos a dejar.
Y tenemos el force consistent.
Yo creo que con estos, a ver, voy a mirar un poco por encima.
Pero yo creo que con estos tenemos suficiente.
Este, este es súper problemático.
Pero bueno, está divertido.
Así que lo vamos a dejar.
Yo creo que con esto ya tenemos suficiente.
Esto ha sido nada para configurar un poco nuestro entorno, ¿vale?
Con TypeScript, su configuración y ya está.
No hemos hecho todavía nada.
Así que ahora falta empezar a crear nuestra API.
Vamos a instalar una dependencia que es de sobras conocida.
Porque para crear APIs en Node es súper utilizada.
Es express.
En este caso, con un guión E mayúscula que significa que vamos a guardar la versión exacta, ¿vale?
Y como una dependencia.
Así que, ¿ves?
La dependencia express me la he guardado sin el caret.
¿Ves que TypeScript me la ha puesto con el caret?
Eso es porque no he puesto que me la guardase como exacta.
Pero bueno, no pasa nada.
Se quita el caret.
Yo quito el caret porque normalmente me gusta controlar, a mí, las versiones que se instalan, ¿vale?
Vamos a empezar con el código.
Creamos una carpeta source.
A mí me gusta en todos los proyectos crear una carpeta source.
Aquí cada uno que haga lo que quiera.
Pero a mí me gusta porque así en source siempre vas a tener el código fuente.
Y luego puedes tener el código compilado en otras carpetas.
Entonces tú tienes source, que es lo que vamos a tener.
Index.ts.
Voy a hacer un poquito más grande el editor para que lo veáis bien.
Y ahora aquí vamos a hacer nuestra magia.
Vamos a importar express, desde express.
Y aquí, mira, ya empiezan los problemas.
O sea, solo he puesto una línea y ya se está quejando.
Luego veremos cuál es el problema que nos está diciendo y cómo lo arreglamos.
Vamos a crear una aplicación con express, ¿vale?
Esto lo hemos visto ya en anteriores clases.
Le decimos que nuestra aplicación va a utilizar express.json, que es un middleware que transforma la rec body a un JSON, ¿vale?
A un objeto JSON.
Que así, pues, los posts y la información que tú envías a tus endpoints de la API, pues es mucho más fácil.
Si no, hay que hacer transformaciones a mano y es un poco coñazo.
Vale, le vamos a decir a qué puerto va a levantarse nuestro servidor.
Ponemos el treadmill.
Y vamos a crear ya un endpoint que le vamos a llamar ping, ¿vale?
Vamos a tener rec y res.
Rec es request y res es response.
Y de la rec y la response lo que vamos a hacer, bueno, un console.log.
Esto para ver más que nada en el servidor que todo está funcionando bien, que alguien ha hecho un ping.
Y vamos a contestar la request con una response y le vamos a enviar como response pong.
Ya tenemos esto.
Bueno, pues, ya inicializamos nuestro servidor y le decimos que en el puerto este, en el 3000, ¿vale?
Vamos a estar escuchando.
Nuestra aplicación va a estar escuchando en el puerto 3000.
Y cuando eso ocurra, lo que quiero es indicar aquí un console.log que diga que el servidor está en el puerto.
Pues, le ponemos aquí, puerto 3000.
Esto es un template string y evaluamos el port, ¿vale?
Ya está.
Ya tenemos nuestra aplicación hecha.
Bueno, no está hecha exactamente.
Vamos a ver los problemas que nos está dando ya.
Ya nos está chivando algunas cositas, ¿vale?
Entonces, lo que nos está chivando por aquí, fíjate.
Nos dice aquí, el parámetro rig tiene implícito un tipo any.
El tipo any en TypeScript significa que puede ser cualquier cosa.
¿Por qué pasa esto?
Bueno, en realidad esto está pasando ya.
El error viene porque nosotros hemos dicho en la configuración que esto no puede ocurrir.
¿Ves?
Aquí tendríamos el no implicit any, ¿vale?
No se puede utilizar el tipo any de forma implícita.
Como lo tenemos en strict, pues, esto no puede ocurrir.
Y esto es lo que nos está diciendo.
Pero esto tiene sentido porque, además, esto tiene solución.
Es una solución bastante fácil.
Fíjate que en la primera línea también está en rojo.
Lo mejor que tiene Visual Studio Code es que, como está hecho con TypeScript,
tiene una integración con TypeScript de primera clase.
O sea, el editor está escrito con TypeScript.
Así que ya puedes ver que yo no he configurado nada más y el editor ya se está quejando de cosas.
Vale, pues, en la primera línea lo que nos está diciendo es que no puede encontrar una declaración para el módulo express.
O sea, que no tiene los tipos, básicamente, los tipos de TypeScript.
Y entonces te dice, mira, puedes probar hacer esto, arroba types, barra express, para ver si existen o añadir una nueva declaración y tal.
¿Qué pasa?
Que te puede, cuando utilizas TypeScript, te pueden ocurrir dos cosas.
Una, que tu paquete, el paquete que quieres utilizar, pues, sí que tenga los tipos ya incorporados dentro del paquete.
Y entonces, al importarlo, ya lo detecta TypeScript con sus tipos y todo.
Y fantástico, genial.
O te puede pasar lo que nos está pasando aquí, que hay algunos paquetes que no tienen tipos creados o no los tienen en el paquete.
Pero hay gente que está creando esos tipos para que tú los puedas utilizar.
Esto ocurre, ves que aquí me está diciendo este types, arroba express.
Esto es porque hay una web que hay un montón de este tipo de paquetes.
A ver si lo puedo, a ver si está, ah, no, acuerdo cómo era la web.
Esta es, definitely type.
Y esta tiene, pero, un montón, un montón de paquetes con sus tipos y todo esto.
Que lo puedes utilizar y buscar si está el paquete este que quieres y ya está.
Y entonces, ves, aquí tendrías Node, hay un montón.
Casi todos los interesantes están.
Así que tiene miles, eh, o sea, tiene miles de paquetes.
En este caso, pues, aquí tenemos este, que ya es el que necesitamos.
Pues, lo vamos a instalar para, justamente, que nos deje de dar este problema.
Nos vamos a Terminal, la voy a abrir aquí.
Y voy a instalar, pues, types barra express.
Y lo ponemos como dependencia de desarrollo también.
Importante, eh, siempre que sean los tipos, siempre como dependencia de desarrollo.
Que no queremos, o sea, no sirve para nada que les estén como dependencia normal.
Si alguien, alguna vez, muchas veces hay gente que me pregunta, oye, pero ¿por qué haces esto?
O sea, ¿qué sentido tiene que tú, por un lado, pongas dependencia de desarrollo y dependencias normales, no?
O sea, ¿qué diferencia hay?
Más allá del nombre, que es obvio, ¿no?
El nombre es obvio.
Porque unas son de desarrollo y otras son dependencias normales.
¿Qué diferencia hace entre una y otra?
Pues, es mucho más de lo que crees.
¿Por qué?
Imagínate que yo este paquete, que ahora se llama Express TypeScript, pudiese ser instalable en otra máquina.
O sea, o un paquete publicable.
¿Qué pasa?
Que si tú dices que es una dependencia, si tú esto lo mueves aquí, lo que pasa es que si otra persona se instala este paquete para utilizarlo,
instalará todas las dependencias.
Y claro, TypeScript, pues esto lo podéis ver aquí, packagephobia, y podéis ver lo que ocupa.
Lo que estaríamos haciendo es que, sin necesidad, esa persona tendría que instalar 58 megas.
Y no es necesario, porque no es cierto que sea una dependencia del paquete.
El paquete debería ser utilizable sin necesidad de TypeScript.
Pero si quieres desarrollar, entonces sí que necesitas TypeScript.
Entonces la diferencia, que parece una chorrada, pero no lo es, es que las dependencias que tú pones en DevDependencies,
cuando alguien utiliza esta dependencia como una subdependencia de su proyecto, no se instalan.
Es un cambio sutil, pero es súper importante, te lo puedo asegurar.
Porque esto a veces ha pasado, y lo que ocurre es que, pues claro, tú haces una instalación,
imagínate que aquí tienes Webpack, TypeScript, no sé qué, no sé cuánto,
y ese paquete, pues ocupa cientos de megas.
Entonces tú, los módules, ocupa, vamos, la vida.
Bueno, ya tenemos los tipos, y por lo tanto, fíjate, desde que he instalado los tipos, ya no me da el problema.
Pero sí que me está dando aquí como, me está dando su cosita, ¿no?
Me está diciendo aquí cosillas que me dice, oye, ¿qué pasa aquí?
Ya no me da el problema de que no tengo los tipos, y cuando me pongo encima del request,
fíjate que ahora no me dice que es eni, sino que me dice que es una request,
que tiene un root parámetros, barra ping, o sea, esto ya tiene los tipos de Express.
De hecho, yo si pongo aquí rec y hago un punto, ves que ahora me sale aquí un autocompletado,
esto es porque ha recuperado los tipos, y ahora es capaz de autocompletarlo.
Y son todos los tipos, además te dice el que está deprecated.
Este de param te dice, está tachado porque está deprecado.
Es bastante interesante.
Y de cada uno, además, te podría decir, va, pues que sepas que si intentas acceder aquí a esto,
pues esto debería ser un no sé qué.
Bueno, en este caso, porque body no tiene ese campo.
Pero lo que quiero decirte, que de cada uno de los tipos de la request, te lo dice.
Igual con la response, ¿vale?
En este caso, fíjate que aunque eso ha mejorado y ya sabemos, ¿no?
Res, pues es una response, y send, pues esto te devuelve tal, o sea, genial.
Pero fíjate que me dice este warning, porque reg is declared, pero el valor no se utiliza.
Este error viene por lo que hemos hecho aquí.
¿Ves? El node unus parameters, que lo hemos puesto a true.
Para solucionar esto, puedes hacer diferentes cosas.
Yo a veces hago esto, que es poner esto.
TypeScript tiene una excepción, que si tú pones el parámetro con un guión bajo, pues ya lo ignora.
O puedes poner el guión bajo y poner a lo que te refieres.
Esto puede venir bien, sobre todo cuando estás ignorando más de una, ¿vale?
Yo en este caso seguramente utilizaría este, porque como que me molesta la vista ver qué es la request.
Y ya lo sé, es demasiado evidente que la request, porque ya me sé que ese callback siempre la request es el primer parámetro.
Si lo quieres tener claro, pues puedes hacer esto.
Pones el guión bajo y luego pones lo de la request.
Como tú prefieras, ¿eh?
No hay uno que sea mejor que el otro, pero bueno, son dos formas de verlo y ya está.
Ahora que ya tenemos esto, bueno, lo primero que podríamos hacer, aunque sea una tontería,
sería hacer un mpn run tsc para ejecutar nuestro script que hemos hecho aquí antes, ¿vale?
Que sería el de compilar.
Vamos a ver si todo funciona bien y no tenemos ningún error.
Vale, fíjate que ha funcionado bien, no se ha quejado de nada.
Ahora, si vamos aquí a nuestro explorador, ¿ves que ahora tengo la carpeta build?
Pues tengo la carpeta build porque yo lo he puesto aquí en el tscconfig que el outdir fue ese build, ¿vale?
Pues fíjate cómo me lo ha compilado.
¿Ves que te había dicho que podía ser Common.js o Inmascript Modules?
Aquí tiene la diferencia, que aquí en este caso pues está utilizando require.
¿Ves? Aquí se ve require.
Pero esto del import default y todo esto, esto es porque hace que sea compatible con los dos modos.
Y eso lo está haciendo también gracias a la configuración que le hemos dicho por aquí,
que, a ver, es este, este, es module interop, para que pueda funcionar de las dos formas.
Y esto lo hace TypeScript por ti y no tienes que preocuparte nada más, ¿vale?
Ahora podríamos probar obviamente build index.js.
Bueno, de hecho esto, en lugar de ejecutarlo aquí a saco, vamos a poner aquí ya un script
que le vamos a llamar start, ya sabéis que ello funciona a través de scripts
porque me parece que son súper cómodos y si el día de mañana alguien quiere ejecutar esto
es mucho más fácil hacer un npm run y ver todos los scripts y ver qué hace cada uno.
Pues hacemos un npm start, ya tenemos en el puerto 3000 esto funcionando,
nos vamos aquí a nuestro navegador, localhost 3000 y, ah bueno, esta barra es normal porque no funciona,
pero si vamos al index, en la barra ping deberíamos tener algo funcionando.
Ping, pong, vale. No es la mejor API del mundo, estamos empezando.
Pero lo importante es eso, ¿no? Y además ves, aquí tenemos el console.log que ya había puesto aquí.
Muy bien, pues venga, sigamos. Ya tenemos esto, pero ya vamos a ver que, claro,
yo si ahora aquí hago un console.log, someone ping here, y yo que sé, por lo que sea,
queremos ponerle también la fecha, ¿no? New date to local datestream, ¿no?
Y yo guardo los cambios, pues vamos a tener que estar, pues otra vez compilando, ejecutar y tal.
No te preocupes. A ver, alguien puede decir, ah, pues vamos a utilizar Node.mon y escuchamos los cambios y tal.
Node.mon es una utilidad que te permite hacer esto, pero hay una utilidad que es bastante más cómoda
para poder hacer esto. También podríamos instalar un paquete que se llama TSNode,
pero bueno, como es de modo desarrollo lo que queremos hacer, vamos a utilizar uno que es un poquito más especial,
que utiliza TSNode. Es una mezcla entre TSNode, que hace la conversión a TypeScript,
de TypeScript a JavaScript para Node, y Node.mon, ¿vale? Es npm install tsnode.dev y también dependencia de desarrollo.
¿Qué es lo que hace esta dependencia? Pues esta dependencia, que la vamos a utilizar aquí,
le vamos a poner un dev y vamos a hacer TSNode.dev, ¿vale? Y le vamos a decir que nos ejecute source index.ts.
Esta dependencia va a hacer, por un lado, levantar, o sea, va a ejecutar y compilar todo lo que tenga que compilar
y va a estar escuchando los cambios para volver a hacer la compilación. Así que hacemos un empie en run.dev
y ahora ves, nos ha hecho el servidor, nos dice que está aquí en el puerto 3000.
Si vamos aquí, pues veremos ahora en la terminal que sí que puedo ver la fecha.
Si quito la fecha, vamos a quitar la fecha, ¿vale? Otra vez. ¿Ves? Lo ha refrescado ya, volvemos aquí
y ahora me debe salir aquí, ¿ves? Ya sin fecha. O sea, que ya está escuchando los cambios,
que es justo lo que necesitamos y mucho más fácil de ir cambiando, ¿no? Ahora podemos ir haciendo los cambios.
Ya tenemos que reiniciar el servidor con cambios. Vamos a añadir funcionalidad,
porque si no, nuestra API va a quedar. Te explico un poco lo que vamos a hacer.
Vamos a hacer, imagínate que tenemos un intrépido viajero, un piloto de aviones entre la comunidad.
Vamos a decir que Tiktools, ¿vale? Que es alguien que es muy, muy activo en la comunidad de Discord que tenemos.
Pues Tiktools es piloto de aviones y quiere hacer un seguimiento de sus experiencias, de sus viajes aéreos.
Entonces quiere poder guardar en un diario todos sus viajes, con la fecha de entrada, las condiciones meteorológicas,
la visibilidad, si fue buena, si no sé qué. Y un texto libre con un comentario para decir,
ah, pues me sentía bien, me sentía mal. Y entonces los datos que vamos a hacer,
tengo por aquí el enlace para que los veas, serían algo así, para que veas cómo es el tema, ¿no?
La idea, la fecha, el weather, si estuvo lloviendo, si hizo buen día, la visibilidad y el comentario.
Ah, pues me dio mucho miedo, pero menos mal que estoy vivo. Vale, pues este sería un poco el JSON que vamos a hacer,
que vamos a devolver y el que vamos a crear. Así que vamos a crear, aquí en source, vamos a crear una nueva carpeta
que le vamos a llamar roots. Roots de rutas, ¿vale? Pero no de rutas aéreas, sino de rutas para express.
Y vamos a añadir aquí un diaries.ts, ¿vale? Aquí vamos a crear, como todas las rutas, para nuestra API,
para esta pequeña aplicación que quiere Tiktools, que no necesita una UI, porque ya sabe utilizar la terminal
y lo va a hacer todo con terminal y con la API y tal. Importamos express, eso es lo primero.
Importamos express y ahora vamos a crear un router. Y esto lo hacemos con express.router, ¿vale?
Ahora aquí vamos a tener dos endpoints. Uno en router.get, vamos a tener este rec res y vamos a tener otro
que nos va a permitir añadir entradas. Así que también en la raíz. Ahora veremos por qué es en la raíz,
porque alguien dirá, ¿en la raíz? No, pero no se quedará así. Lo que vamos a poder hacer es decirle
en qué path tiene que utilizar este router. En un ratito lo veremos. El rec, este ves que ya me está fallando, ¿por qué?
Porque me dice, oye, que rec no lo usas. Vale, pues le ponemos el guión bajo. Fíjate que ya estamos
reutilizando cosas que hemos aprendido. En el get por ahora vamos a decir que aquí vamos a hacer
un fetching all diaries o entry diaries, ¿vale? Y en el post igual, vamos a decir por ahora.
Luego haremos esto de verdad. Saving a diary, ¿vale? Y esto, pues obviamente tenemos que hacer
un export default de router. Fíjate qué es lo que comentaba antes. Aquí estamos utilizando
enmascript modules. Enmascript modules son básicamente imports y exports.
Tú si ves import y exports, son enmascript modules. ¿Vale? Estos son
esmodules. Y common.js sería así. Express, require, express. Que esto es lo que se utilizaba
antiguamente. ¿Vale? Esto sería common.js. Pero fíjate que aunque nosotros utilizamos
enmascript modules, luego cuando se compila, utilizamos common.js. ¿Vale? Solo para que
tengas en cuenta que vamos a estar utilizando siempre enmascript modules, pero se compilan
common.js. ¿Vale? Pues ya tenemos aquí nuestras rutas para nuestra API con la que vamos a
ir trabajando. Ahora lo que tenemos que hacer es importar básicamente esto. Vamos a importar
el diary router desde barra routes barra diaries. ¿Vale? Me dice que está declarado y no lo
uso. Pues no te preocupes que lo voy a usar ahora mismo. App.use. Y aquí le decimos, mira,
en la ruta barra API barra diaries, quiero que utilices este diary router. ¿Vale? Así
es como funciona. Fíjate que ya he guardado los cambios y esto está ahí que no para. Así
que si vamos aquí a API barra diaries y le damos aquí, ¿vale? Fetching all entries.
A ver, todavía no aparecen, pero ahora vamos a trabajar para que aparezcan. Lo importante
es que nuestra ruta funciona. Vamos pasito a pasito. Suave, suavecito. Venga, ahora,
la parte de las rutas, yo haría aquí, esto lo podéis hacer como queráis. Yo os doy
esta estructura de directorios porque a mí me parece que está bien. Por ejemplo,
yo separaría lo que sería un poco la lógica de las rutas con las propias rutas. Yo intentaría
hacer la mínima lógica posible dentro de las rutas. Así que podéis crear una carpeta
services y aquí, pues, decir diary services, por ejemplo. O le podéis llamar diary porque
ya que está dentro de services. Así que vamos a crear también, aparte, el
diaries.json, que hemos visto aquí este json que teníamos aquí. Luego te explicaré
un poco sobre esto y algunas cosas que podemos hacer al respecto. Pero por ahora voy a dejar
este json porque me interesa explicarte una cosa de TypeScript. Vamos a tener un archivo
json, que al final, pues, es un objeto, bueno, un array de objetos en este caso. Y vamos
a ver cómo lo podemos importar, qué problemas nos puede dar y todo esto, ¿no? Y es bastante
interesante porque pensad que esto es un json aquí, pero esto podría ser un fetch, podría
venir de una base de datos. O sea, lo que vamos a ver es replicable para cualquier situación
en la que recuperas un json de cualquier manera, ¿vale? Sólo para que tengas en cuenta.
Vale, vamos a importar el diary data, ¿vale? Del json. En este caso, esto es lo que te digo
que podría ser un fetch, podría ser cualquier cosa. Diaries.json. Fíjate que ya aquí me está
diciendo que no puede encontrar el módulo y entonces me está dando aquí alguna pista.
Ahora le echamos un vistazo, ¿vale? Por ahora, aquí en el diary de services vamos a tener
un método que nos va a devolver todas las entries, las entries del diario. Fíjate que
todavía no he escrito TypeScript. O sea, fíjate, yo lo único que he estado haciendo es .ts,
.ts, pero todavía no he escrito TypeScript, pero en cambio ya tengo un montón de ventajas
de TypeScript que hemos ido viendo. Y verás que sin escribir TypeScript puedes tener un montón
de ventajas. O sea, es bastante curioso. Porque mucha gente con TypeScript se vuelve
un poco loco de, no, no, no, tengo que empezar a tipar, a poner tipos y tal. Y no es tan así.
Y de hecho, vamos a ver que puede ser una mala práctica. Te voy a enseñar cómo tienes
que siempre intentar hacer el mínimo número de tipos y reutilizarlos al máximo. Lo vamos
a ver en la clase. Vale, vamos a tener para recuperar las entries y para añadir una.
Por ahora le voy a poner esto que es null, porque no lo vamos a hacer ahora, lo haremos
después. Exportamos cada uno de los métodos para utilizarlo fuera. Volvemos al problema
que teníamos, ¿vale? Fíjate que en este import ya me dice, oye, no puedo encontrar
este módulo. Considera usar Resolve JSON Module. ¿Por qué? Porque por defecto depende
de la configuración que tengas de TypeScript. Pero bueno, te la quiero comentar para que sepas
cómo funciona esto, que esto no es magia y tal. Por defecto, TypeScript no es capaz
de importar esto tal cual, ¿vale? Se lo tienes que decir tú que quieres soportar este tipo
de archivos. Así que voy a añadir aquí una configuración más que le vamos a llamar
Resolve. Bueno, no le vamos a llamar, es que es su nombre, no hay otra. Resolve JSON Module.
Y la vamos a poner a true, porque por defecto ya has visto que es false. Así que la guardamos.
Ves que además esto, cuando cambia las opciones, también reinicializa la compilación de TypeScript.
Así que perfecto. Si volvemos a Diary Services, ya no tengo error. Perfecto. Esto es justamente
lo que nos interesaba. Pero, ¿qué pasa con esto? Esto es un problema muy típico
de TypeScript, porque TypeScript es una maravilla, pero tiene sus límites.
TypeScript, una de las cosas que tiene es la inferencia de datos. Lo que quiere decir
es que a través de cómo tú utilizas los parámetros o las variables o lo que sea,
te dice, ah, pues este objeto es de este tipo y tienes estas propiedades y tal. Fíjate aquí
en el getEntries, que yo me he puesto encima y me dice, ah, sí, mira, el getEntries
lo que hace es devolver, pues, un idNumber, un dateString, weather, o sea, un objeto,
bueno, un array, porque fíjate que tengo aquí array, un array de objetos y tienes aquí
todos los tipos. Y yo no he dicho nada, o sea, es que esto va solo. Pero no quiero
que sea exactamente así, ¿no? Porque si nos fijamos en el diaries.json, el weather y el
visibility, aunque son strings, yo me gustaría que tuviesen un número limitado
de strings, ¿vale? O sea, aquí no puedo poner yo lo que me dé la gana, no. Esto tiene
que ser rainy, sunny, no sé qué, igual que el visibility, pues puede ser good, bad,
lo que sea, por... O sea, quiero que tenga un número limitado, no que sea un string
y ya está. Por lo tanto, vamos a empezar a tipar lo que serían los objetos de nuestra
aplicación, ¿vale? ¿Cómo lo hacemos? Pues lo que vamos a hacer por aquí, en source,
vamos a crear un nuevo archivo que le llamamos types.d.ts. Esto es un patrón bastante frecuente,
de hecho, TypeScript busca este fichero. Tú le puedes cambiar en el package.json, puedes
configurar que busque este fichero o busque cualquier otro con otro nombre. Pero yo te
recomiendo que siempre utilices esto porque por defecto es el que busca. Aquí es donde
se supone que tienes todos los tipos de, en este caso, de este paquete. Puedes tenerlos
desperdigados en más de un fichero, importando tipos de diferentes sitios y tal. Pero bueno,
en este ejemplo lo vamos a dejar todo aquí y veremos además cómo lo vamos iterando
y todo esto. Empezamos por el weather. Es un tipo que queremos exportar porque lo vamos
a necesitar en más de un sitio. Así que exportamos un tipo porque podemos crear los tipos que
queramos. Esto lo vimos en la clase anterior, pero bueno, vas a ver que no es complicado porque
simplemente decimos quiero tener un tipo que es weather, ¿vale? ¿Y weather qué puede
ser? Pues como yo le podría decir que, vale, no, quiero que sea un string. Pero le he dicho
no, es que no es un string porque el weather tiene un número limitado de string que puede
ser. Puede ser sunny, puede ser rainy, o sea, lluvioso. Puede ser que está nublado o puede
ser que tiene un poquito de viento o de tormenta, ¿vale? Lo mismo para la visibilidad. Vamos a
decir visibility, ¿vale? Le decimos que puede ser que sea genial, que esté bien, que está
ok o que, bueno, ha sido un desastre y casi me mató. Y entonces ahora vamos a poder crear
una interfaz, ¿vale? Ahora te explico un poco la diferencia entre interfaz y tipos. Pero
al final los tipos es que nosotros estamos creando tipos, igual que existe el tipo number,
el tipo string, el tipo bolean, todos los tipos primitivos existen. Pues tú puedes crear
tu propio tipo y puedes decir que es una serie de strings, que sea una serie de números
en concreto, tipo de array, un montón de cosas. Una interfaz, digamos que es más un
contrato que debería tener un objeto. En este caso vamos a decir que el objeto diary entry es un
objeto que además va a tener un id number. Esto es muy parecido a lo que nos estaba diciendo ya
Tagscript, ¿verdad? Que era un id number, no sé qué. ¿Ves? Si me pongo aquí, dice id number date
string. De hecho, me lo podría copiar y pegar, mira. Y más o... ¡Ay! Me ha copiado lo que ha querido.
No me ha copiado lo que quería. Bueno, no pasó nada. Id number date string. Pero antes me había dicho que
el weather era un string. Y yo no quiero que sea un string. Quiero que sea weather.
Lo mismo con el visibility, ¿no? Visibility. Pues me había dicho que era un string. Yo no
quiero que sea un string. Creo que sea del tipo visibility. Y luego teníamos un comentario
que hemos dicho que sea un string. Vale. Pues ya estamos como definiendo nuestro contrato.
Ahora, ¿cuál es la diferencia? ¿Cuándo debería utilizar types y cuándo debería utilizar
interfaces? Por si tienes la duda. Muchas veces son intercambiables. Muchas veces. De hecho,
te puede generar esto, ¿no? Porque tú también puedes tener un type.
para un objeto. O sea, esto lo podríamos hacer con un type y nos podríamos quedar bastante
a gusto. ¿Ves? Esto funciona correctamente. Pero, ¿qué pasa? Que las interfaces, la diferencia
que tienes es que tú una interfaz está pensada para ser extendida. Por ejemplo, tú una interfaz
podrías decir, vale, pues tengo ahora una interfaz que sea, yo qué sé, especial diary entry
y que esto lo que hace es extender de la otra interfaz, de diary entry.
Esto en cambio, ¿ves? Esto aquí podríamos decir que, pues, el flight number, ¿no? Y le decimos que esto es un number.
Esto lo que hace es que el special diary entry tenga todas estas propiedades más esta que estamos indicando aquí.
Esto se puede hacer con tipos también. Lo que pasa es que queda un poquito más raro. O sea, lo que en tipos tú harías es crear.
No sería tanto extender, sino que estaríamos creando otro tipo diferente. O sea, estaríamos el special diary,
le podríamos, bueno, dos, le podríamos decir. Le podríamos decir que es el diary entry y también la propiedad
flight number y tal. Pero fíjate que ya es diferente, ¿no? El cómo se expresa esto es una cosa distinta.
En realidad estás creando como otra cosa. Podría ser compatible. Pero yo te recomiendo que si es una interfaz,
es algo que tienes que extender, pues, que lo hagas como interfaz. Y lo otro, si es una cosa que se va a quedar
más fija, más fija o que vaya a ser como composición, entonces que lo hagas como un tipo. Bueno, solo te digo esto.
Bueno, hay una diferencia que sí que es importante que tenés que tener en cuenta, que no puedes tener dos veces el visibility.
O sea, yo esto, por ejemplo, type visibility. O sea, al final lo que haría es, lo estarías o sobreescribiendo
o te podría dar un error. En cambio, las interfaces sí que puedes tenerlo más de una vez y se irían añadiendo.
O sea, es una diferencia importante. Pero bueno, yo creo que lo mejor es eso, los tipos más fijos,
las interfaces más para extender. Vale. Pues ahora que ya tenemos más o menos esto claro,
ya tenemos las interfaces, unos tipos. Este no lo vamos a utilizar, que lo sepáis.
Ya tenemos esto, weather, visibility, perfecto. Pues nos vamos a los servicios.
¿Qué pasa con estos servicios? Pues que este getEntries, que ahora me está devolviendo esto,
yo en realidad le quiero decir, no, no, tú no vas a devolver este objeto que tú crees.
Tú lo que vas a devolver es lo que yo te diga. Así que vamos a crear aquí una constante,
diaries, y ya sabemos que en TypeScript hay que poner aquí dos puntos y el tipo,
que tenga pues number, lo que sea. En este caso, lo que queremos que sea un array de
diaryEntry, que es el tipo. Fíjate que cuando he hecho esto, el autocomplete,
le he dado enter y ya me lo ha importado automáticamente. Esto es una de las maravillas
que tiene justamente TypeScript. Vale. Pues le digo que es un array de diaryEntries.
Y esto es un diaryData. O sea, estoy importando el diaryData y lo que estoy intentando hacer
aquí, fíjate, es decirle, vale, voy a crear una constante que se llama diaries,
que es del tipo array, que es un array de diaryEntries, que es justo lo que acabo de crear.
O sea, un array de este tipo de objeto. Y esto viene de diaryData.
Pero no le está gustando esto nada. Esto no le está gustando.
Porque cuando me pongo encima, esto, un consejo de TypeScript que os doy ya, ¿vale?
Esto, cuando veis esto, esto da más miedo, porque empieza esto a ser imposible de leer.
Lo que os recomiendo es que lo leáis al revés, no de arriba a abajo, sino de abajo a arriba.
Porque cuando se lee de arriba a abajo, es muy difícil.
El problema en realidad está en esta línea. ¿Ves? Te dice,
typeString is not asignable to typeWeather.
Porque aquí estamos teniendo justamente el mismo problema que tenía aquí en el GetEntries,
que es que el weather, él dice que es un string, y yo le estoy diciendo que no,
que no es un string, que esto es, el weather en realidad es uno de estos tipos.
Y él dice, no, no, esto puede ser lo que sea, porque en el JSON este puede ser lo que sea.
Y no, no es así. Entonces, ¿qué es lo que le podemos decir?
Para arreglar esto, hay diferentes formas de hacerlo,
y una de ellas, que yo creo que sería la correcta en este caso,
sería utilizar la aserción de tipos.
O, bueno, hay gente que le llama afirmación de tipos.
A mí me gusta más la aserción de tipos.
Que es decirle, no, no, no te preocupes, que este JSON que hay aquí,
yo sé que es de este tipo en concreto, ¿vale?
Que tiene esta interfaz en concreto.
Siempre, la aserción de tipos, básicamente, es obligarle a TypeScript
a considerar que esta constante tiene que funcionar de una forma.
Y esto es súper típico siempre que trabajas con JSONs
que vienen de APIs externas, o que estás importando, o lo que sea.
Porque es como que tú no estás controlando la creación de ese objeto, ¿vale?
Te puede venir cualquier cosa.
Entonces, tú eres el que tiene que decir a TypeScript,
no, no, no te preocupes, que sé lo que hago.
Fíjate que esto lo que está diciendo el DiaryData,
lo tienes que tratar como si fuese un array del DiaryEntries.
Y a partir de aquí ya te dice, ah, vale, pues ya está, pues Diaries.
Ahora, en el GetEntries, en lugar del DiaryData, voy a utilizar Diaries.
Y de esta forma, el GetEntries, ahora me dice que lo que devuelve
es un array del DiaryEntry.
Ya está, punto.
Esto puede ser una forma.
Yo lo que te diría, esto siempre lo tienes que controlar.
Tienes que evitar utilizar la aserción de tipos siempre que puedas.
O sea, no lo tienes que utilizar a no ser que sea necesario,
como en este caso, que es necesario porque este JSON viene así y ya está.
O cuando haces un fetch y le tienes que decir,
no, mira, la respuesta de esta JSON la tienes que tratar como si fuese esto.
Este es el caso súper típico.
Pero siempre que puedas, pues evítalo.
A ver, hay otras opciones.
Os voy a enseñar otra opción que a mí no me gusta y ahora os explicaré por qué.
Pero la enseño porque se hace también.
Vamos a importar el DiaryEntry de los tipos, ¿vale?
Punto, punto, types.
¿Ok?
Y aquí lo que podríamos tener es un DiaryEntries,
decirle el tipo, ¿no?
Que es un array de DiaryEntry.
Pero lo que haríamos aquí justamente es tener el JSON.
Es tener todo este JSON.
Claro, esto, además, es que aquí lo podemos hacer porque lo podemos hacer,
pero esto no es tan fácil como hacerlo y ya está.
Porque es lo que te digo, ¿no?
Ahí, si esto lo haces en un fetch, esto no lo puedes controlar.
Esto a veces tiene sentido cuando es un JSON que tienes dentro de tu aplicación.
Lo que ocurre con esto, fíjate,
es que yo ahora puedo ir al DiaryEase.json este
y en lugar del .json utilizar el .ts.
Ah, no, .ts no es necesario.
Ah, y aquí te voy a explicar otra cosa interesante.
Ahora, ya no necesitaría nada de esto, ¿vale?
Porque justamente lo que miramos el TypeScript este,
cuando yo estoy creando este array, ya le estoy diciendo el tipo que es.
Entonces ya dice, ah, no, es que el weather es del tipo weather.
O sea, aquí no es que sea un string vacío, o sea, no que pueda ser cualquier string,
sino que ya me ha dicho que es de este tipo.
¿Por qué no me gusta esta solución?
Uno, porque es muy idílica, ¿no?
Es una solución que te puede ocurrir de vez en cuando.
Y, o sea, de vez en cuando en el sentido de que tú tengas el JSON.
Dos, porque eso tiene un coste en runtime, ¿no?
El transformar, el crear esta estructura de datos en JavaScript,
transformarla, luego pasarla a JSON, no sé qué, no sé cuánto,
y no es necesario.
Y luego porque puede ser más tricky de lo que parece.
Porque luego te puede dar otro tipo de problemas, ¿vale?
Lo veremos incluso más adelante,
no sé si lo llevaremos a ver que nos dé problema.
Pero este weather, cuando luego lo pasemos a otra estructura,
puede ser problemático.
O sea, no es tan fácil como parece.
Deberíamos utilizar aquí entonces la estructura y tal.
Yo la enseño solo para que lo sepáis,
pero recomiendo más que utilicéis, o sea,
que conozcáis la de JSON y creo que la forma correcta
de tener estos datos aquí guardados
y no pasarlos a TypeScript me parece innecesario.
Mi opinión, ¿eh?
Entonces, ahora te quiero enseñar otro tema
que es bastante interesante.
Y es por el hecho de que, claro, yo cuando he hecho esto,
fíjate que ahora hago .barra diaries,
pero ahora aquí tengo dos archivos,
uno .json, uno .ts.
Y entonces tú te puedes estar preguntando,
¿vale?
¿Y cuál de los dos coge?
¿Cuál de los dos toma?
¿Cuál de los dos importa?
Porque los dos, o sea, se llaman igual
y tú aquí no has puesto extensión.
A ver, esto es cómo se resuelven los módulos en TypeScript, ¿vale?
Hay como una cadena de, digamos, de prioridad
y va de derecha a izquierda, de hecho.
Por ejemplo, en TypeScript lo primero que va a buscar
sería tcx, luego, perdón, tcx, la extensión tcx,
luego buscaría .ts, luego buscaría .note,
luego buscaría .js, luego .json, ¿vale?
Yo, a mí, esto es una cosa que no me gusta mucho,
sé que se puede llegar a cambiar y tal.
Bueno, a mí me gusta mucho especificar siempre los tipos.
De hecho, bueno, he puesto .js,
no sé por qué he puesto .js,
porque no .js y no sé por qué ha funcionado.
De hecho, es que me lo ha importado automáticamente.
Ha sido raro.
Claro, me lo ha importado automáticamente y me lo ha puesto.
Bueno, el caso, que en enmascriptmodules,
aunque esto parezca mentira,
es obligatorio poner las extensiones en enmascriptmodules, ¿vale?
O sea, deberíamos poner .ts.
Pero en TypeScript no es obligatorio.
Entonces, a mí me gusta poner las extensiones
porque es cómo funciona la especificación.
Pero en este caso, si no ponéis las extensiones,
al menos que sepáis cómo funciona.
O sea, si tenéis estos ficheros,
fíjate que aquí me ha recuperado el .ts,
en lugar del .to.json, ¿vale?
Solo para que lo tengas controladísimo.
Porque al evitar poner la extensión,
pues puede ser un poco problemático.
Bueno, en este caso voy a ponerle la barra baja,
porque no lo vamos a utilizar,
pero así lo tenemos ahí de ejemplo.
Y utilizamos el .json este.
Y volvemos a poner este,
que queremos que esto sea un array de diary entry, ¿vale?
Cualquiera de las dos está bien,
pero bueno, solo para que lo sepas.
Ahora que ya estamos escribiendo mucho código,
una cosa que es bastante importante
y mucha gente, pues, suele,
le puede costar un poco,
y no sé por qué.
Pero bueno, yo te voy a decir cómo lo haría yo.
Y aquí cada uno que lo haga como quiera.
Ahora empezamos a tener mucho código.
Y bueno, yo qué sé,
pues me puede escapar por aquí un punto y coma.
Y en otros sitios, pues a lo mejor no.
Aquí voy a poner punto y coma, lo que sea.
Y en el diarist, pues bueno,
aquí hay muchas tabulaciones, lo que sea.
El caso, vamos a poner un linter.
Mi recomendación, porque esto es un mundo,
como lo, bueno, es que utiliza Slint, de hecho,
es que utilicéis TS estándar.
Yo sé que hay algunos que os pueden gustar y tal,
pero TS estándar al final es un linter
que utiliza Slint por debajo.
Lo que pasa es que viene con un montón de configuración
de la que no te tienes que preocupar
y es súper fácil de utilizarlo
y te olvidas y ya está.
Esa es mi recomendación.
Si no, podéis utilizar Slint con Slint TypeScript Parser,
configurarlo a vuestro gusto,
hacerlo paso a paso y tal.
Pero TS estándar, la verdad,
es que tiene una configuración que está súper bien.
¿Ves?
Hemos instalado.
Y ahora, para utilizarlo,
si ya tenéis una extensión en vuestro editor,
en mi caso yo ya tengo Slint,
lo que podéis hacer para utilizarlo,
yo lo he instalado.
Ahora aquí podría utilizar el lint.
Creo que este es estándar, tal cual.
Y lo podríamos ejecutar.
Vamos a ver.
Lint.
A ver si funciona.
Sí.
¿Ves?
Ahora lo está ejecutando.
Este es estándar.
Ya me ha encontrado un montón de problemas.
Oye, esto no puede ser.
Esto no sé qué.
Esto no sé cuánto.
¿Vale?
Ahora lo que pasa es que si yo voy al fichero,
pues no me está diciendo dos problemas.
Una forma de hacer que esto funcione súper fácil
es en el editor,
ahí en el Package JSON justamente,
añadir un SlintConfig.
¿Vale?
¿Por qué?
Porque todas las extensiones de Visual Studio Code
y tal lo que hacen es leer este tipo de configuración.
Y aquí lo que le vamos a indicar es,
mira, por un lado tienes que extender
la configuración de Slint que estoy utilizando,
extiende de nodeModules,
barra, testStandard,
barra, SlintRc, JSON.
Y en este caso además hay que decirle también
cuál es el parser y qué proyectos es el que estamos utilizando.
O sea que en el Parser Options,
bueno, el parser no hace falta decírselo,
pero sí le tenemos que decir,
para el parser, el de TypeScript,
le tenemos que decir dónde está la configuración.
Así que este proyecto le decimos que la configuración
la tenemos en tsconfig.json.
Con estas cuatro líneas de código ya,
bueno, no sé ahora si va a funcionar,
porque veo que, a ver,
no me la ha hecho.
A ver si he puesto esto bien.
SlintConfig,
ah, espérate porque hay veces,
hay veces que hay que hacer esto.
Esto es un poco tan,
hay que cerrarlo.
No sé por qué,
eso ya creo que es una cosa más divisiva de Studio Code,
pero si no, ahora lo veremos.
Y de hecho veremos si...
En el...
Voy a aparecernos aquí Slint ahora.
Vale, ¿ves aquí?
Y, ¿ves?
Ahora sí que ha funcionado.
No sé, no sé por qué pasa.
Supongo que una vez que tiene la configuración,
pues no sé qué.
Pero bueno,
cierras Editor,
lo vuelves a abrir,
y ves,
ahora me dice todo esto.
Si lo tienes bien configurado,
que te salgan los errores,
y además al guardar,
¿Ves?
Voy a guardar,
¡pum!
Y me los ha solucionado todos.
Y eso, pues,
para todos los archivos, ¿no?
Pues vas entrando.
¿Ves que en este caso ha hecho esto?
Esto es porque el linter tiene esto,
que puedes hacer los arrays de esta forma,
o los puedes hacer así,
Darity,
Entry,
y tal.
Este tipo,
en los dos casos es el mismo,
y en el caso del linter,
te utiliza la que es más corta.
Pero fíjate que es que no importa.
Yo puedo utilizar los arrays así,
y cuando guarde,
pues me lo va a poner como le guste y ya está.
Fíjate que además aquí,
te dice Missing Return Type on Function.
¿Sabes?
O sea,
que ya te está diciendo,
oye,
que esto aquí me tienes que decir cuál es el tipo
que tienes que devolver.
No puede ser así tan...
Así que,
bueno,
vamos a ponerle a este undefined por ahora.
Y vamos a decirle que devuelve un undefined.
¿Vale?
Y en este caso,
pues esto es un array de entries.
Pues le vamos a poner que es un array de entries.
Está bastante bien este linter.
Yo es el que os recomiendo.
Si os gusta configurarlo,
pues nada,
lo hacéis a mano.
También tiene configuración este,
tampoco es que sea muy problemático.
Pero bueno,
creo que funciona bastante bien.
Ya tenemos el linter.
Ya tenemos un poquito de,
hemos visto tipos,
diary entry y tal.
Ya hemos visto cómo funcionan los módulos de Node y tal.
Te voy a enseñar una cosa que yo creo que te da,
esto es la regla de Pareto,
¿vale?
El 80-20.
Hay una cosa en TypeScript que se llaman los tipos de utilidad.
Utility types o como lo quieras llamar.
Tipos de utilidad,
¿no?
Hay un montón disponibles de filtro,
de require,
de no sé qué,
no sé cuánto.
Pero hay dos que yo creo que son muy interesantes que domines.
Y vamos a ver por qué.
Imaginemos que en el diary services,
yo ya tengo el export const del get entries,
que esto me devuelve todas las entradas que tengo en el diario,
pues imagínate que quiero tener otra que le llame,
pues,
get entries,
pero sin el comentario,
porque tiene información confidencial,
por ejemplo.
Entonces le llamo get entries without sensitive info,
sensitive info,
¿vale?
Y le digo que esto lo que me va a devolver es un array,
pero me va a devolver un array de algo que es un tipo especial.
No va a ser diary entry,
como lo hemos visto antes,
sino que va a ser un diary entry non-sensitive info diary entry.
¿Vale?
Vale,
expression inspector,
espérate,
la he liado,
que aquí he puesto un array.
Así.
Ahora,
vale,
fíjate que me dice que no existe.
Ahora vamos a crear este tipo,
¿no?
¿Qué tiene que hacer este tipo?
¿No?
Pues yo lo que quiero justamente es un tipo que tenga todo lo que hemos visto
antes en el types.
Fíjate aquí.
Ah,
mira,
aquí también me dice de quitar las comas.
Y este irregular space,
¿Ves?
El linter es que es necesario.
Vale,
pues quiero un diary entry,
pero sin el comentario.
Una cosa que hace mucha gente,
y no deberías hacer nunca,
es esto.
¿Cómo le hemos llamado esto?
Non-sensitive info diary entry.
Vale.
Esto de aquí.
¿No?
Ya está.
Tenemos una interfaz que tiene todo lo que queremos,
menos el comentario.
Ya está.
Pues arreglado.
Esto es una mala práctica.
¿Por qué?
Porque TypeScript,
tú tienes que pensar que cuando,
es lo que te digo,
TypeScript siempre deberías intentar utilizar el mínimo número de tipos posible.
Justamente la gracia que tiene TypeScript.
Sé que suena raro,
porque llamándose TypeScript cualquiera puede decir,
no,
quiero hincharlo a tipos.
Pero es que no hace falta.
O sea,
tú lo que tienes que hacer es controlar en sitios puntuales los tipos.
¿Vale?
Y luego iremos viendo cómo hay sitios en los que no hace falta porque ya los puede inferir y puede ser mejor incluso que lo hagas tú.
Porque significará que hay sitios en concreto que lo estás haciendo bien.
En este caso,
esto lo que estamos haciendo es crear otra interfaz aquí que en realidad vamos a tener que mantener,
que puede cambiar y claro es que es igual que esta.
Entonces lo que deberíamos hacer aquí en realidad es crear esta interfaz a partir de la diary entry.
Esto es lo que siempre tienes que hacer.
Tener el menor número de interfaces y tipos posibles y jugar con ellos para crear otro tipo de tipos e interfaces.
¿Vale?
¿Por qué?
Porque así el diary entry siempre será tu fuente de la verdad y no tendrás que estar duplicando todo esto.
En este caso,
en lugar de hacer esto,
una forma que podrías hacer es utilizar un tipo de utilidad que podría ser el pick.
Pero ahora veremos otro que es todavía mejor para este caso.
Así que podríamos exportar un tipo en lugar de una interfaz que le llamamos,
¿cómo le hemos llamado aquí?
Non-Sensitive Info Diary.
Vale,
pues le llamamos así.
Y aquí le decimos que utilizamos pick para el tipo del diary entry.
Y lo que queremos ahora es decirle todas las propiedades que sí que nos interesan.
Pues diríamos id y también date y también weather.
Y también visibility.
¿Vale?
Ahora,
claro,
esto se cerraría aquí y ya estaría.
Ahora con el non-Sensitive este lo vamos a importar aquí en los tipos y ya lo tendríamos.
¿Vale?
Y ahora si mirásemos esto,
fíjate cuando me pongo encima que me dice,
mira,
este tipo es con id,
date,
weather y visibility.
Y no está el comentario por ningún sitio.
Hay otra forma de hacer esto,
¿vale?
Otra forma sería hacer lo contrario.
Y es otro tipo de utilidad que también te recomiendo que tienes que conocer.
Este lo voy a comentar y nos vamos a quedar con el otro.
Vamos a crear este y en lugar de utilizar el pick vamos a decir el omit,
¿vale?
Para omitir uno en concreto.
Así que le decimos del diary entry le vamos a decir que omita el comment.
Y ya está.
De esta forma se va a quedar con todos excepto con el comentario.
Con que este es un,
estas dos son de las más potentes y muchas veces te pueden simplificar mucho
los tipos que vas creando.
Evita empezar a crear tipos y tipos y tipos.
Cuando vas viendo que tienes trozos que ya te van a servir,
es genial porque esto además va muy alineado con el tema del domain driving design,
de siempre tener una forma de referirte a algo en concreto,
¿vale?
Entonces cuanto menos objetos de tu dominio,
del lenguaje que tengas,
pues mejor.
Ok,
pues esto sería.
Omitimos el comentario y tal.
Esto va alineado con una cosa que te quiero explicar que es súper importante.
Además,
venga,
quito los tipos,
ya tenemos el getEntries y todo.
Vamos a ver qué pasa con esto.
Porque yo tengo este getEntries sensitive info,
yo lo voy a utilizar aquí,
¿vale?
Vamos a decir aquí there is without sensitive info,
¿vale?
Lo utilizo
y aquí en esta constante,
pues voy a tener este valor,
¿no?
Si yo ahora aquí intento acceder a la posición cero y al comentario,
pues me va a decir que la propiedad comment,
pues no existe.
Así que en este caso está haciendo bien su trabajo,
¿no?
Dirías,
vale,
genial.
Está diciendo que no puedes acceder ahí.
Vale.
Vamos a hacer algo.
Nuestra API se está quedando un poco muerta porque no la estamos tocando mucho.
Así que lo que vamos a hacer es utilizarla.
Para ello,
este getEntries without sensitive info,
la voy a utilizar...
Diary...
Todo como DiaryServices.
Vamos a utilizar ya nuestros servicios
y aquí en el get lo que voy a hacer ya,
este fetch no sé qué,
no sé cuántos,
pues vamos a darle ya un poco de vida
y vamos a decirle que
DiaryServices.getEntries,
esto es lo bueno,
el autocomplete,
cuando empiezas a tener estas cosas ya,
autocomplete.
Vale.
Ahora,
la terminal creo que se me ha tenido que cerrar el modo dev.
Voy a volver a ejecutarlo.
Ya lo tenemos por aquí.
Puerto 3000.
Vamos a irnos al puerto 3000
a ver qué tenemos aquí.
Un problema.
Eso es lo que tenemos.
Vale.
Fíjate.
Fíjate qué ha pasado aquí.
Y esto es otra cosa súper importante,
¿no?
De saber y que te quede clarísimo
que TypeScript no funciona en runtime,
¿vale?
¿Qué quiere decir en runtime?
Lo que quiere decir es que TypeScript
solo funciona de forma estática,
solo funciona en tiempo de compilado.
Por lo tanto,
lo que está ocurriendo aquí es que
yo tengo este getEntries without sensitive info
porque yo quería justamente en los tipos de este,
tipos,
yo quería que omitiese el comment.
Y de hecho,
en el services,
fíjate que yo estoy diciendo,
no, no,
esto devuelve un non-sensitive info directory entry.
Y funcionar está funcionando
porque me está diciendo TypeScript
que sí,
que no tiene un comment,
que este tipo no tiene un comment.
Y cuando lo intento utilizar aquí en el código,
me dice,
oye,
que no,
que no utilices el comment,
que no tiene esa propiedad.
Pero,
¿qué pasa?
Que cuando yo voy aquí a roots
y le hago un res.send
y hago esto,
pues no es capaz,
TypeScript,
de detectar que este objeto en realidad
tiene el comentario.
No es capaz.
Y no me lo está filtrando por arte de magia,
¿vale?
Eso lo tenemos que hacer nosotros.
Eso lo siento,
pero lo tenemos que hacer nosotros.
Así que,
lo que tenemos que hacer,
este trabajo,
es cosa nuestra.
Lo que deberíamos hacer en el getEntries este,
este diaries que teníamos aquí,
lo que tendríamos que hacer es un map,
justamente.
Voy a ponerlo aquí en otra línea.
Retour diaries.map.
Aquí podríamos,
pues nada,
coger y recuperar el date,
el weather,
el visibility,
visibility.
Y esto lo que haría,
pues sería devolver,
bueno,
lo podemos poner en otras líneas,
pero bueno,
no pasa nada.
La idea,
el date,
el weather
y el visibility.
¿Vale?
Visibility,
aquí,
hasta aquí.
Esto lo tenemos que hacer nosotros.
Ahora sí,
vamos aquí
y ahora sí que no está el comentario.
¿Por qué?
Porque he recuperado todos los campos
excepto el comentario.
A ver,
es lo malo,
o sea,
TypeScript nos está controlando
todo lo que sería estático,
pero si queremos que eso ocurra realmente
luego en el,
cuando el cliente llega a esta información,
tenemos nosotros que filtrarla,
¿vale?
Ok,
vamos con otro tema.
Vamos a ver cómo,
cómo se trata el tema de los undefined también,
porque TypeScript es listo,
pero tampoco es,
es mega,
mega,
mega inteligente.
O sea,
que otra vez vamos a ver un poco este problema,
pero desde otro prisma.
Vamos a tener otro método aquí,
que le vamos a llamar
findById,
porque vamos a querer encontrar una entrada en concreto,
¿vale?
y esto,
vamos a decirle que tiene una ID,
vamos a decir que tiene el number,
porque hemos visto aquí en Diaries,
¿no?
Que esto tiene que ser un número,
así que un number,
y a través del number,
este método lo que va a devolver es un diary entry,
porque tiene que encontrar uno.
Y este,
este problema que vamos a ver aquí,
es de lo que te salva TypeScript en el,
no voy a decir el 80%,
pero si no es el 60,
vale,
con la ID vamos a buscar una ID en concreto en el array,
¿no?
Pues vamos a recuperar la entry,
de Diaries,
find,
vamos a tener un diary,
de .id,
que sea igual a la id que estamos buscando,
y que nos devuelva la entry,
¿vale?
Pero fíjate el problema que hay aquí,
y esto es de lo que te suele salvar TypeScript,
porque esto es lo que siempre normalmente nos olvidamos de hacer en JavaScript,
¿no?
Nos está diciendo,
fíjate que yo estaba súper contento,
digo,
no,
esto me devuelve un diary entry,
pero me dice,
eh,
que cuando tú haces un find,
esto lo que te puede devolver es un diary entry o un undefined,
¿vale?
¿Por qué?
Porque un find,
si no encuentra esta ID,
te devuelve un undefined,
por lo tanto,
aquí TypeScript ya ha encontrado una difurcación que puede existir,
de,
no,
no,
tú te crees que esto va a ocurrir siempre,
y esto no es así,
o sea,
puede ocurrir que esto sea undefined,
así que controla esto,
por favor,
porque no me da la gana dejar que esto funcione.
Entonces,
lo que debemos hacer en este caso,
pero bueno,
todavía tendríamos que hacer un poquito más de cosillas,
sería aquí decir que también puede devolver undefined,
¿vale?
Vale,
ok,
este entry no solo puede ser un diary entry,
sino que también puede ser un undefined.
Esto lo que nos va a obligar a partir de aquí,
es en controlar siempre,
que esto nos pueda devolver un undefined,
y tendremos que poner if,
if,
if,
y no nos permitirá acceder a una propiedad de este entry directamente,
sin un if antes,
¿vale?
Vamos a ver un poco,
por ejemplo,
si nos vamos a las rutas,
¿no?
Y aquí vamos a crear una ruta más,
root get,
y le ponemos aquí dos puntos id,
y con esto lo que vamos a hacer,
pues primero,
el entry,
vamos a recuperar el diary en concreto,
un diary en concreto,
del diary services,
find by id,
y además,
fíjate aquí,
la de cosas que tiene,
donde empieza la magia de TypeScript,
con un poquito,
con un poquito,
¿de dónde podemos recuperar el id?
Bueno,
pues esto lo tenemos aquí,
que es un parámetro de la request,
por lo tanto,
tenemos que hacer rig.params.id,
y aquí,
ya,
ah,
vale,
es que,
¿ves?
Como lo vamos a usar,
le tenemos que quitar la barra baja,
¿vale?
Vale,
ahora aquí,
ya empieza a quejarse,
dice,
oye,
es que .id,
fíjate que esto es un string,
y tú me has dicho que el find by id,
es un número,
los params siempre vienen como string,
por lo tanto,
tienes que transformarlo,
si no,
no le va a gustar,
lo puedes hacer con un diary operator,
o lo puedes hacer si queréis con el number,
a mí me gusta más el unary operator,
pero bueno,
para que lo sepáis,
¿vale?
Ok,
ahora sí que tendríamos el diary,
pero,
vale,
es que esto me lo he copiado del otro,
tú aquí,
en el diary,
si tú pones diary,
punto,
diary,
diary,
punto,
vale,
comen,
no sé qué,
no sé cuánto,
fíjate lo que ha hecho,
automáticamente,
imagínate que yo intento acceder a uno en concreto,
¿vale?
fíjate que yo hago diary,
punto,
y le digo,
vale,
quiero ir al weather,
mira,
¿ves que me ha añadido automáticamente un optional chaining?
Porque dice,
eh,
que esto puede ser undefined,
esto no funciona así como esperas,
entonces,
esto es otra de las magias que tiene TypeScript,
¿no?
Que está detectando que,
ostras,
esto puede venir undefined,
cuando vayas a hacer autocomplete,
te voy a poner esto,
porque si no,
me voy a quejar,
porque esto puede ser undefined,
aquí está una de las magias,
uno de los checks más típicos,
a ver,
podríamos hacer,
por ejemplo,
podríamos hacer también una ternaria,
y tampoco se quejaría,
resend diary,
bueno,
en este caso es que no se quejaría si lo enviaríamos directamente,
pero lo que podemos hacer,
sería esto,
¿no?
Que si ha encontrado un diary,
si lo ha encontrado,
que lo envíe,
y si no,
bueno,
claro,
dice que será diferente a nivel y tal,
es que es brutal,
porque entre el linter,
entre el linter,
y el,
entre el linter y tidescript,
es que no te dan,
no te dan,
vamos,
a que te puedas equivocar,
oye,
que no puedes un objeto,
pues es nulable,
no sé qué,
y ya te hace el check,
¿no?
Te dice,
oye,
que pues hazlo así,
lo podéis hacer como queráis,
¿vale?
Podéis mirar que el diary,
que sea undefined,
que no sé qué,
y entonces devolverlo,
y de esta forma,
si no lo encuentra,
pues que sea 404.
Esta es la gracia un poco que tiene,
¿no?
Ahora,
estaríamos un poco en el mismo problema,
¿no?
O sea,
no en el mismo problema,
pero como devuelve el comentario,
si miramos a ver aquí en el diary,
si ponemos aquí el 1,
¿ves?
Otra vez tendríamos el problema este del comentario,
si lo que queremos es que devuelvan el diary services,
le decimos que devuelva,
hemos puesto un diary entry,
pero le decimos un non-sensitive,
no sé qué,
no sé cuántos,
al final,
¿ves?
Es que el comentario se queda,
o sea,
que de nuevo deberíamos decir aquí,
pues si hay un entry,
que me va a volver a hacer el truco este del non-nul,
diferente a null,
entonces pues voy a quitar el comentario,
esto sea el rest of diary,
esto viene de entry,
y entonces devuelvo entry,
devuelvo rest of diary,
porque de esta forma he quitado justamente el comment,
pero fíjate,
¿ves?
Que,
oye,
notal code path return a value,
esto viene de la configuración que hemos hecho al principio,
¿ves?
Lo del implicit return,
este,
no implicit returns,
¿vale?
¿Por qué?
Porque un return implícito aquí sería que esto hace un return undefined,
pero no le gusta que sea implícito,
quiere que lo escribas,
pues nada,
ahí lo tienes,
y ahí ahora sí funciona correctamente,
tendríamos que poner esto así,
¿vale?
O podríamos,
otra cosa sería devolver el entry,
porque aquí ya debería,
pero bueno,
yo pondría,
sería más explícito todavía,
pondría undefined,
si no os gusta esto,
lo podéis desactivar,
o sea,
no estáis obligados,
pero bueno,
os quería que lo vierais,
ya hemos hecho hasta aquí,
bueno,
a ver,
bueno,
ahora veis que no está el comentario,
justamente lo que queríamos,
ya hemos recuperado uno,
ya hemos recuperado todos,
pues ahora lo que nos falta es añadir un nuevo diario,
¿no?
Hacer un post,
ser capaz de hacer un post,
vamos a ir cerrando por aquí,
el package.jsr también,
vamos a dejar esto por aquí,
vale,
para el post,
vamos a ir aquí a la,
a la ruta,
al diaries,
y teníamos aquí el post,
que por ahora no estamos haciendo nada,
aquí es otra cosa que vas a ver,
que incide en lo que he dicho antes,
que hay que reutilizar al máximo,
mira,
vamos a poner que de la request del body,
nos tiene que llegar el date,
el weather,
el visibility,
y el comment,
la id no,
porque la vamos a generar nosotros,
del rock.body,
vale,
y esto,
le ponemos así,
ahora utilizamos res,
así que,
no,
que no se queje,
vale,
on the student,
on the news,
comments,
vale,
no pasa nada,
eso lo utilizamos ahora un momentito,
entonces,
vamos a crear,
new diary entry,
una nueva entrada en el diario,
para esto utilizaremos también,
nuestro servicio,
que será un add entry,
que ahora todavía no lo hemos creado,
lo crearemos ahora,
y que es lo que le tenemos que pasar,
pues nada,
todo,
date,
el weather,
visibility,
y,
el comment,
fíjate que se me pone todo esto en rojo,
porque se está poniendo nervioso,
porque dice,
pero,
pero que estás intentando,
si nada de esto existe,
te lo estás inventando,
sí,
pero ahora lo arreglo,
vale,
que pasa,
que este add entry,
que sí que lo habíamos creado,
pero fíjate que lo habíamos dejado vacío,
y ya me dice,
oye,
que le estás parando,
le estás pasando cuatro argumentos,
y esperaba ninguno,
no te preocupes,
yo ahora te lo arreglo,
a ver,
pues el add entry,
pues hemos dicho que tendríamos,
ah,
bueno,
por ahora vamos a poner solo los parámetros,
aquí directamente,
el date,
que es un string,
el weather,
que tiene que ser de tipo weather,
vale,
me lo ha importado automáticamente,
visibility,
visibility,
os recomiendo un montón,
siempre que hagáis autocomplete,
lo seleccionéis,
le dais al enter,
porque cuando,
fíjate,
de aquí arriba no está,
y si haces el autocomplete,
y le das,
te lo añade,
vale,
es que si no,
te puede volver un poco tarumbá,
y el comentario,
que es un string,
vale,
esto ya no debería devolver un undefined,
debería devolver un diary entry,
y aquí vamos a hacer toda la magia de nuestra función,
vale,
así que,
¿qué es lo que tiene que devolver todo esto?
Bueno,
con todo esto,
vamos a crear un new diary entry,
vale,
que va a tener la id,
aquí la id podéis hacer dos cosas,
una,
pasarle el diaries.length,
y que daos súper a gusto,
¿por qué?
Porque cada vez que añadáis,
que vais a añadir uno,
la longitud del array sería,
justamente,
bueno,
lo podemos ver aquí,
en el json,
id1,
id2,
3,
4,
5,
claro,
si las id son en orden,
pues se supone que ahora la longitud de esto,
pues sería 1,
2,
3,
4,
o sea,
sería length más 1,
¿vale?
Y ya así siempre,
esto sería teniendo en cuenta que los ids siempre sean consecutivos.
Otra cosa que podéis hacer,
pues,
mathmax,
y lo que hacéis es de diaries.map,
de cada diary,
pues recuperáis la idea,
y más uno,
ya está.
Y entonces miráis todos los que hay,
la idea más alta,
más uno,
ya está.
De esta forma os aseguráis que aunque no estén consecutivos,
por ejemplo,
si este 4 fuese el primero,
por equimotivo,
lo ponéis aquí,
pues ya no teníais problema.
Bueno,
os lo explico por si os interesa,
para que lo sepáis,
que os guste más.
Vamos a dejar este que se ve que,
como que somos más listos.
Ahora,
utilizamos el date,
utilizamos el weather,
utilizamos el visibility,
hemos creado justamente la idea,
tenemos el visibility,
nos falta el comment,
y ya con esto,
lo que podemos hacer es diaries.push,
porque vamos a empujar justamente esta entrada,
porque la queremos guardar,
new diary entry,
y lo que hacemos es devolverlo,
new diary entry.
¿Vale?
Y ahora con esto,
con esto de aquí,
ahora sí que hemos actualizado esto,
veo que se sigue quejando,
vamos a ver por qué,
porque igual a veces,
a veces se queda un poco pez,
si veis que os da un error de antes,
a veces cuando tiene errores,
a veces no hace que se vuelva a refrescar.
Es raro,
pero a veces pasa,
me ha pasado en este momento.
¿Veis?
Ahora funciona correctamente,
¿no?
O sea,
que ahora sí que podríamos añadir uno.
Lo podríamos intentar,
¿vale?
O sea,
podríamos ir al post,
añadirlo y todo esto,
pero antes,
hay una cosa que es demasiado evidente
y quiero que lo arreglemos
antes de seguir,
¿vale?
Fíjate aquí,
en los campos,
¿no?
Cuando hago un add entry,
fíjate que es date,
weather,
visibility,
comment,
y voy aquí y tengo date,
string,
el weather,
el weather,
visibility,
visibility,
bla,
bla,
bla,
no,
¿vale?
No,
¿por qué?
Porque ya estamos otra vez con lo mismo
de estar repitiendo una y otra vez
las mismas cosas
y no tiene sentido.
Entonces,
primer consejo que te doy,
¿vale?
El primero,
siempre te tienes que referir a las cosas
con los mismos nombres.
En este caso,
que le estamos llamando add entry,
a mí me choca un poco el add entry,
¿vale?
Porque debería ser add diary,
más que add entry.
Entonces,
yo intentaría siempre tener como,
utilizar siempre los mismos nombres del dominio.
Ah,
no sé por qué add diary no existe
en el types,
direct services.
Ah,
porque no lo he guardado.
No sé,
no sé por qué,
pero,
parece que no lo había guardado.
A ver ahora.
Bueno,
vale,
add diary,
eso es lo primero.
Luego,
en el router,
en el router que tenemos por aquí,
¿vale?
En el router,
en lugar de pasarle los parámetros de esta forma,
le podríamos pasar otra cosa,
¿no?
Que sea más un new diary entry,
o sea,
un objeto.
Le vamos a pasar un objeto,
en lugar de todo esto,
le podríamos pasar un objeto.
Obviamente,
ahora se nos queja,
porque add diary no espera que sea todo un objeto,
sino que lo que espera es que fuesen separados,
bueno,
pues vamos a arreglarlo aquí en la diary.
¿Ves que ahora estamos pasándole separado cada uno de los parámetros?
Aquí lo que le vamos a tener que pasar es justamente un new diary entry.
Este new diary entry que habíamos hecho aquí,
le voy a cambiar el nombre,
new diary,
y vamos a poner aquí,
new diary,
new diary.
¿Cuál es el problema?
Que el new diary entry este,
pues fíjate que ahora dice,
oye,
pero esto de qué tipo es,
que tiene un tipo estricto,
que no tengo ni idea,
bueno,
no pasa nada,
porque todos estos objetos ni siquiera hace falta que los controlemos tanto,
porque una vez que lo tipemos,
ya deberíamos estar más controlados.
Así que lo que vamos a hacer es que los añada a todos,
¿vale?
Este new diary entry,
pues hace este new diary entry,
y ya está.
Tú aguardalos ahí todos y ya está.
¿Qué pasa?
Que todavía nos dice,
oye,
que esto tiene un tipo implícito de ending,
que esto qué es,
que me digas qué es,
que no soy tan listo.
Bueno,
pues vamos a volver a nuestros tipos.
En nuestros tipos,
si nos fijamos,
al final lo que estamos devolviendo aquí en el router,
lo que queremos añadir,
tiene date,
weather,
visibility,
y comment.
Que si miramos los tipos,
es exactamente lo mismo,
pero sin una idea.
Por lo tanto,
el tipo que debe ser es new diary entry.
Y esto lo que tienes que hacer es un omit del diary entry y que omita la idea.
Fíjate que esto va teniendo bastante más sentido,
o sea,
estamos reutilizando todo el rato el diary entry y lo estamos como moldeando según el uso que necesite.
En lugar de estar ahí todo el rato creando nuevos y nuevos y nuevos,
pues ahora tiene más sentido.
El add diary le añades un new diary entry con una idea.
Esto debería tener el resto de los new diary entries que necesitas.
Bueno,
este de aquí menos la idea.
Y ya lo tendrías.
El new diary te debería devolver un diary entry porque el diary entry sí que tiene la idea.
No sé si esto ha quedado claro o ha sido.
Pero lo que quiero que te quede claro es que intentes siempre mover objetos que tengan un contrato.
¿Vale?
Y en lugar de volverte tarumba creando nuevos contratos para cada parámetro y cada cosa,
pues que básicamente intentes ver lo que tienes que reutilizar en ese aspecto.
¿Vale?
Porque es que si no,
no te acaba esta script.
Y entonces empiezan problemas y tal.
Vale,
vamos a ver si esto funciona porque yo esto...
¡Ay,
espérate!
Weather...
¿Qué le ha pasado a este?
¿Qué dice?
Add diary and services...
¿Ves?
Pero esto no sé ahora.
Si...
Si es que...
Ah,
porque esto no lo estoy utilizando.
¿Vale?
Esto lo vamos a quitar.
Ya no estamos utilizando estos tipos aquí directamente.
¿Vale?
Y la terminal.
No sé si se está refrescando o no.
Bueno,
vamos a confiar que sí.
A lo mejor es que sí que se refresca.
Y soy yo que...
Que aunque veo que no...
¿Ves?
Ah,
no,
pero otra vez.
Como que se queda...
Como se queda en caché.
Porque fíjate que esto ya no lo tenemos aquí.
Add diary este.
¿Ves?
Que ya tengo el diary string.
No sé.
Se vuelve un poco loco.
No sé si lo cachea,
lo está cacheando o algo.
Pero ves,
ahora funciona correctamente.
Pero me está enseñando el código de antes.
Bueno,
equi.
El tema,
vamos a probar si funciona todo esto.
Vámonos aquí al Thunder Client
de Visual Studio Code.
Y aquí en el Thunder Client,
que es como un postman,
por si no lo conoces,
tampoco tiene mucha historia.
HTTP,
barra,
barra,
localhost,
3000,
API,
client,
client,
se iba a decir.
Diaries.
¿Vale?
Vamos a probar primero el get.
¿Vale?
Todo funciona bien.
Me devuelve el 4 primero.
1, 2, 3.
Perfecto.
Vamos a probar al post.
Y para eso un body,
vamos a crear aquí un JSON.
Voy a hacer esto un poquito más chiquitito.
Y aquí vamos a crear un JSON con la fecha,
que vamos a poner hoy que es.
Hoy es el 021,
el 06,
el 06.
Vamos a poner el weather,
que hoy ha sido sunny.
Vamos a poner el visibility,
pero a verlo escrito bien,
que es good.
Y vamos a poner un comentario,
que le vamos a decir que,
awesome day,
I'm Goku.
Vale.
Y le vamos a dar a send.
Vale.
Pues ha funcionado correctamente,
¿no?
Lo ha añadido,
la id 5,
con todo esto,
id 5,
porque era el número máximo,
si le doy a send,
debería ser 6.
¿Vale?
O sea,
que los está añadiendo.
Si ahora hago un get,
y le doy a send,
pues me debería,
¿ves?
Los que he ido añadiendo.
No me devuelve el comentario,
porque es información confidencial,
y la estábamos filtrando correctamente.
Vale.
Hasta aquí,
bien.
Pero,
hay diferentes problemas aquí,
que son interesantes.
Esto es como,
todo lo optimista,
¿no?
Todo ha ido bien,
porque hemos sido súper optimistas,
de que todo iba a ir bien.
Pero,
vamos a volver,
al router,
un momento,
por aquí.
Routes,
vale.
Aquí.
Claro,
fíjate que aquí,
en el rec body este,
el problema,
como tal,
es que,
este date,
weather,
fíjate que,
esto es any.
El date es any.
El visibility es any.
Comment,
any.
Todo esto es any,
any,
any.
Esos son los tipos que tiene,
porque no se está controlando,
lo que le puede pasar,
justamente,
un usuario.
Bueno,
es que,
de hecho,
si yo voy aquí al post
y empiezo a crear
y le digo que la fecha
le paso un true,
al weather le paso Kikos,
el visibility,
oh yeah,
y yo le doy aquí al send,
pues fíjate que me ha destrozado
TypeScript.
A tomar por saco TypeScript.
Tanto TypeScript,
tanto TypeScript,
¿no?
Y al final,
lo que está pasando aquí
es que estas validaciones
no las estoy haciendo.
El date que TypeScript me decía
que era un string,
yo le he pasado un boleano.
El weather que TypeScript
dice que ese tipo es tal,
yo le he pasado Kikos.
Y aquí tenemos el problema,
que es que TypeScript
es muy listo,
pero tampoco tanto,
¿no?
O sea,
que al final,
el problema que tiene TypeScript
es que funciona
de forma estática,
¿vale?
Piensa en un linter,
¿vale?
TypeScript es como un linter,
es como un test.
Es un test
que no puede tener en cuenta
lo que ocurre
o lo que añade el usuario.
Y esto es súper importante
porque mucha gente
se cree que esto
te lo arregla TypeScript
y no es así.
Así que ya ves
que las validaciones
las tenemos que hacer,
¿vale?
Y que para TypeScript
este request.body
es una caja negra
que una vez que está en el código
ya dice,
ah, sí, no, no,
esto va a ser un string,
esto va a ser tal,
pero antes no sabe lo que es.
Te tienes que asegurar tú
de que la información
que le vas a pasar
es la correcta.
Así que vamos a,
nada,
vamos a revisar la información,
vamos a darle cañita a esto,
vamos a añadir validaciones
y vamos a ver
todos los retos
a los que nos vamos a tener
que ir enfrentando
de pasar una estructura,
un objeto
donde todo es any
a lo que justamente
nosotros necesitamos.
Así que vamos poco a poco.
Vamos con el router.
Ya os digo,
vamos a empezar por aquí
porque vamos a poner
un try-catch, ¿vale?
Un try-catch aquí,
bien grande y bien hermoso.
Donde si falla,
pues nada,
hacemos un res status
de 400
y enviaremos el e.message
del error que sea.
Ahora,
todo esto que estamos haciendo aquí
lo vamos a hacer
en el try, ¿vale?
Es lo que vamos a intentar
que funcione bien.
Eso sí,
le vamos a dar una vueltecita
a esto porque ya ves
que todavía no estaba,
o sea,
petar no estaba petando
de ninguna forma.
Lo que vamos a hacer
es tener
este new directory
entry que estamos creando aquí,
lo que vamos a hacer
es más bien
crearlo en otro sitio.
Lo que vamos a tener aquí
es un added directory entry.
Esto ya es cuando se ha añadido.
Pero crearlo,
lo vamos a crear
en un paso anterior.
New directory entry.
Y lo vamos a crear
con una función
que le vamos a llamar
to new directory entry.
Y esto es una cosa
que vas a necesitar bastante
normalmente que hacer
cuando estás utilizando
TypeScript con Express
o con cualquier API, ¿vale?
Vamos a hacer algo.
¿Qué pasa?
Que ahora mismo
este new directory entry
es en lo que le vamos
a pasar directamente aquí.
Ya no hace falta
que hagamos nada.
Donde va a ocurrir
toda la magia
de extraer esa información,
asegurarnos que tiene
los tipos correctos
y todo esto,
va a ser este
to new directory entry, ¿vale?
Así que vamos a crear
aquí, vamos a ver,
bueno, vamos a crear aquí
un utils.
Utils es la caja,
es el cajón desastre
donde se mete todo.
Seguramente,
a lo mejor utils
no sería mejor.
A lo mejor deberíamos tenerlo en...
Bueno, lo voy a dejar aquí,
pero os voy a dejar
que en el chat me digáis
yo lo pondría en la carpeta
y lo pondréis donde me digáis.
Bueno, igual lo movemos.
Vale.
Sí tenemos el tipo
de new directory entry, ¿no?
Lo teníamos aquí en types,
pues este lo vamos a volver a utilizar
porque lo vamos a necesitar.
Vamos a ir uno a uno
de todos los que necesitamos, ¿vale?
Lo primero,
el método de esto.
Vamos a hacer un export default
porque este es el,
digamos,
el más importante.
Vamos a ponerlo aquí,
vamos a hacer const,
voy a crear la función
y vamos a hacer un export default
del to new directory entry.
El to new directory entry,
¿qué es lo que le llega?
Le llega un objeto
que puede ser cualquier cosa
y esto es así, ¿vale?
O sea,
puede ser cualquier cosa.
Es que
el input del usuario
es lo que hay.
Pero lo que sí que sabemos
que nos va a devolver este método
es un new directory entry.
Punto pelota.
Eso, clarísimo.
A ver qué le pasa a esto.
Ah, pero nunca he leído, ¿vale?
Digo, a ver que se me está quejando ya.
Y el new directory entry
todavía no está haciendo el reto.
¿Vale?
Pues aquí crearíamos un new entry
que es del tipo new directory entry
y ahí tendríamos nuestro...
Aquí haremos trabajo, ¿vale?
Y devolveremos el new entry.
Así que nada,
vamos, paso a paso.
¿Qué es lo primero que vamos a comprobar?
Vamos a comprobar el comentario.
Por ejemplo,
pues parse comment,
vamos a tener el comentario
que de nuevo
puede ser tipo any.
Este comentario
puedes llamarle comment
o comment from request.
Como tú quieras.
Igual comment from request
tiene más sentido
porque así te queda claro
que este comentario
todavía no está parseado
ni validado ni nada.
Y este método
lo que vamos a devolver
es un string.
Ahora,
lo que vamos a hacer es mirar
si el type of
de comment from request
es diferente a string.
Porque si es diferente a string,
lo que vamos a hacer
es devolver un error
que esto irá luego al try-catch
y le podemos decir
incorrect or missing comment.
¿Vale?
Y si no,
si esto ha ido bien,
pues hacemos un return comment.
Bueno,
comment from request,
perdón.
Comment from request.
Esto lo que nos va a ayudar ya
es parsear el comentario.
O sea,
esto ya lo que podríamos hacer
sería comment
será parse comment
object.com
y así es como iremos haciendo.
Pero ya verás que algunos
tienen más miga que esto.
De hecho,
ya aquí este parse comment
que tiene este type of
no sé qué,
no sé cuánto,
esto lo vamos a sacar
en una función.
¿Por qué?
Porque lo vamos a reutilizar
y además le vamos a dar
un detallito,
¿vale?
Que es importante.
Porque el tema
del parse comment este
es que,
claro,
vamos a utilizar un método
que se llama
isString.
De esto hay utilidades,
¿eh?
O sea,
quiero decir,
hay utilidades que te pueden
hacer validaciones y tal.
Pero creo que es interesante
también que lo hagamos
para que veamos
cómo funciona.
Pero que lo tengas en cuenta,
que puedes hacer
mil millones de cosas
con esto.
Entonces,
aquí lo que posamos
es un string
y este isString
lo que vamos a hacer
es básicamente decir,
vale,
si el type of
es un comment from request,
ahí,
type of string
es string
o también
si el instance of string,
¿esto cómo era?
Ahora no me acuerdo
si era
string
isString
no,
isString no.
¿String?
¿Así?
Espérate.
Ahora no me acuerdo
cómo se escribía esto.
Lo vamos a mirar
en un momento.
Vamos a mirarlo,
eso me pasa por no tener chuleta
y por no utilizarlo mucho.
Pero bueno,
así os explico también
una cosilla de esto.
¿Por qué estoy añadiendo
todo esto,
¿vale?
El problema
es que tú un string,
este string
lo puedes crear así.
Hola, mundo.
¿Vale?
Perfecto.
Y esto es como si deberían
crear los strings
el 80.000 millones
de veces siempre.
Así es como deberían
crearse.
Y a ver,
no es importante,
lo podríamos evitar,
pero el tema
es que los strings
se pueden crear
de dos formas.
Se pueden crear así
o también resulta
que lo puedes crear así.
New string
I'm a string
I'm a string.
LOL.
¿Cuál es el problema?
Que el typeof del primero
es string,
pero el typeof del segundo
será object.
Vale.
Y en cambio,
el instance of...
Ah, vale.
Ahora me acuerdo
cómo se escribe.
El message instance
of string
nos dará
que es false
y en cambio
el otro
nos dirá
que es true.
Y aquí ponemos la B
y nos dirá que es true.
Como hay dos formas
de justamente crear strings,
que ya os digo
que la segunda
no la deberías utilizar
nunca jamás,
¿vale?
Pues por eso
se supone
que no deberíamos
fiarnos solo
del typeof.
No me parece
que sea muy problemático,
o sea,
nos lo podríamos...
Esto ahora es así,
¿vale?
Que luego al final
me he acordado como era.
No debería ser
muy problemático,
pero bueno,
si queréis estar
100% seguro
de que lo estáis haciendo bien,
deberíais hacer esto
para saber
si un string es un string.
Si no,
pues nada,
podéis hacer así,
confiar en que
nadie la va a liar mucho
y ya está.
Y esto es lo que
debería devolvernos,
por cierto,
este string
lo pasamos aquí,
debería ser
un boleano,
¿vale?
Un boleano
y esto
es un string.
Un string
que es un string.
Yo os lo explico
para que lo sepáis
porque esto
alguna vez
se ha visto.
¿Por qué?
Porque hay paquetes
o librerías
que por X motivo
pueden utilizar
el constructor
del string,
vete a saber por qué,
entonces se te llega
como parámetro,
tú dices,
no,
yo quiero que esto
sea un string,
lo voy a revisar,
pam,
y la lías,
la lías.
Bueno,
no tiene por qué pasar
si es código
que tú controlas
porque nunca vamos
a crear un string
de otra forma,
pero si es código
que no controlas
y te llega por parámetro
que sepas
que puede ocurrir.
Bueno,
solo para que lo sepas.
Igualmente,
mira,
lo utilizamos aquí,
si no es un string,
pues hacemos esto
y al menos
pues eso que nos ahorramos
de escribir.
Además,
vamos a ir viendo
poco a poco
que vamos a ir necesitando
esto del isString,
isString,
isString
con otros temas.
Vale,
tenemos la fecha.
Pues venga,
vamos con la fecha.
Para mirar si es una fecha,
para mirar si es una fecha
podríamos tener
que el date
que nos llega
es un string
y podemos
devolverle
también boleano.
Lo que devolveríamos
es
un boleano
del date.parse
y ver si podemos
parsear la fecha.
Y con esto
ya nos diría
si es una fecha
o no es una fecha.
¿Cómo utilizamos esto?
Pues a parsear la fecha.
Parse date,
date from request,
esto puede ser cualquier cosa
como hemos visto
y esto lo que nos debería
devolver
en realidad es un string,
¿vale?
Por cómo lo estábamos haciendo.
Pero bueno,
si se podría complicar
y hacer que nos devolviese
o un date
o un objeto date
y en este caso
es como que esperamos
que el string
tenga un contrato
en concreto.
Así que lo vamos a hacer así.
Si no es un string,
porque sabemos
que tiene que ser un string,
si no es un string
o no es una fecha,
entonces nada,
throw new error,
incorrect or missing date,
¿vale?
Y si no,
pues nada,
devolvemos
la date from request.
¿Y esto dónde lo volvemos?
Ah, esto
así,
esto así,
parse date
y ya teníamos
date,
parse date
object.date.
Estos serían
como los más
aburridos
que hemos hecho hasta ahora
porque ahora viene el weather
y aquí es donde
vamos a tener la historia.
Vas a aprender
una cosita nueva,
¿vale?
¿Qué pasa con el weather?
Vamos a hacer el parse weather.
¿Qué pasa con el weather?
Weather from request.
Que este puede ser any también.
¿Qué es lo que nos tiene que devolver?
Nos debería devolver
un string.
No,
nos debería devolver
un weather
que hemos visto
que era uno
de los posibles strings.
El weather,
que por cierto
lo tenemos que importar,
¿vale?
Para poder utilizarlo,
weather y visibility
que lo vamos a necesitar luego.
El weather,
pues podía ser
sunny, rainy, cloudy, windy, stormy.
¿Vale?
Pues o sea,
que el string
que tiene que devolver esto
tiene que ser uno de ellos.
Para ver esto,
tenemos que mirar,
¿no?
Si el weather from request
no es un string,
pues ya,
si no es un string,
ya sabemos que esto
tiene que ser un error,
¿no?
Incorrect
or missing weather.
Y si no,
pues lo devolvemos.
Pero todavía
tenemos que revisar
algo más,
¿verdad?
Porque el weather
puede ser esa tira
de strings.
Tiene que ser uno de ellos.
Por lo tanto,
lo que deberíamos hacer
es mirar también
si no es un weather.
Y de esto,
pues weather from request.
Y aquí es donde está el tema.
Is weather.
¿Qué podemos hacer aquí
con el is weather,
¿no?
Para que esto,
para mirar
si realmente
el string es
un weather.
Esto debería devolver
un weather.
¿Vale?
Ahora lo que vamos a necesitar
pues es devolver,
pues nada,
mirar todos los weather
que teníamos aquí.
Aunque ya veremos
que esta no es la forma correcta.
Pero todos estos weather
los podríamos tener aquí.
Esto lo transformamos
cada uno de ellos
en una coma.
Tenemos aquí un array.
Y miramos que este array
pues incluya
el string.
¿Vale?
Eh...
Perdona que esto
no lo devuelve un weather.
Esto lo devuelve un bolean.
¿Vale?
Esto sería una forma.
¿Vale?
Y esto funcionar,
funcionaría.
Pero no es exactamente
lo que queremos.
¿Por qué?
Porque esto ya estaríamos
repitiendo justamente aquí
el contrato
que tenemos aquí
en los types.
¿Y qué hemos dicho?
Que no queremos repetir código.
Y menos cuando
son la fuente
de la verdad
de las cosas.
O sea,
si yo ahora aquí
por lo que sea
añado otro
y le pongo que es snow
claro,
esto ya empieza
a tener un montón
de problemas
y de historias
porque aquí
yo estoy haciendo
un check manual
con otros tipos.
Entonces ahí
¿cómo podemos solucionar esto?
Para solucionar esto
existe un tipo de datos
que tienes en TypeScript
que se llama enum
donde puedes enumerar
como diferentes propiedades
que pueden tener
o diferentes valores
que podría tener
una estructura
como por ejemplo
el día de la semana
sabes que puede ser lunes,
martes, tal.
Y lo que te creas
como un objeto
a que te puedes referir a él
y tiene cada uno
de esos keys
tiene un valor en concreto.
Eso sería un enum.
Sería tan fácil
como decir
export enum weather.
Y ahora lo que hacemos
esto es decirle
el weather
¿qué puede ser?
Pues puede ser sunny
y el valor
que tiene este sunny
sería sunny.
¿Qué más puede ser?
Pues puede ser rainy
y el valor que tiene
sería rainy.
El valor
es importante
tanto como la key
pero ya verás
que el valor
tú le puedes poner
lo que tú quieras.
Lo importante
es que luego
de sunny
siempre será
weather.sunny
eso sí que no debería cambiar
pero el valor
puede ir cambiando
y tal
lo que pasa
es que tiene que estar
en sync
con la base de datos
o con la API
o con lo que sea
que utilizas.
Pues así con todo
cloudy
pues venga
cloudy
¿qué más tenemos?
Tenemos el cloudy
tenemos el windy
y tenemos el stormy
¿vale?
Entonces claro
ahora dirás
bueno y esto
¿para qué nos ha servido?
Vamos a quitar ahora este
¿vale?
Esto parece muy similar
¿no?
Esto ¿de qué me sirve?
Pues el tema
es que los enums
no solo
los puedes utilizar
en TypeScript
sino que también
te crea una constante
que puedes utilizar
en tu código
como si fuese
en runtime
o sea
esta estructura de datos
también la vas a tener
disponible en runtime
cuando este código
se compile
TypeScript
te va a dar
como una estructura
un objeto
donde podrás acceder
a esta información
así que
te va a servir
por un lado
para tipar
para chequear
la validez
de tus tipos de datos
pero también
vamos a poder
venir aquí
en el utils
este que teníamos
todo esto
podríamos chequear
ahora el object values
the weather
no
si the weather
perdón
the weather
y ya está
de esta
to parent of type weather
espérate
¿qué he hecho aquí?
¿qué he hecho aquí?
claro
es que ahora
el is weather
esto
debería ser
cualquier cosa
el parámetro
claro
ya está
lo que vamos a ver
claro
es que no
no puedes saber
realmente
que el parámetro
en realidad
tenga que ser un string
lo importante
es que
de todos los valores
que tú tienes en weather
uno de ellos
o sea
que incluya
justamente el parámetro
que quieres ver
¿vale?
de esta forma
sabrás
si es un weather
o no es un weather
y con esto
te quitas
el hecho
de tener que repetir
pues todo el array
y tener los strings
repetidos
y todo esto
y ya podríamos
parsear tranquilamente
el weather
ya teníamos aquí
veníamos aquí
al weather
parse weather
object.weather
y ya estaríamos
¿vale?
aquí tendríamos
nos faltaría todavía
el visibility
con el parse visibility
¿no?
object.visibility
y ya está ¿no?
solo nos faltaría
el visibility
bueno pues nada
vamos a ello
si solo nos falta uno
a ver
otra vez lo mismo
¿vale?
para que
además esto está bien
porque así
nos va a quedar
clarísimo
un enum
¿por qué?
pues porque tenemos
aquí una lista
de valores
que queremos utilizar
también en nuestro código
no solo para validar
los tipos
sino también
para utilizarlos
además
esto
no solo lo puedes utilizar
como hemos visto
con el object values
también podrías hacer
weather.sunny
y esto
te debería devolver
sunny
y lo podrías utilizar
en tu código
¿vale?
entonces
de visibility
pues nada igual
great
pues great
esto debe ser un igual
¿eh?
great
great
good
pues good
ok
ok
y vamos a hacer
exactamente lo mismo
que hemos hecho
de esta forma
¿vale?
ya está definido
tenemos el visibility
nos vamos a utis
vamos con el
is visibility
tendríamos aquí
tendríamos aquí
el visibility
bueno
podríamos ponerle
param
es que da igual
esto nos va a devolver
un booleano
y vamos a mirar
que en el object values
de visibility
pues tenga
justo
incluya
el param
que le estamos pasando
este is visibility
lo vamos a
crear aquí
parse visibility
visibility
from request
que esto puede ser
cualquier cosa
y esto nos devuelve
visibility
¿vale?
si no es un string
el visibility
from request
o
no es
visibility
el visibility
from request
entonces
hacemos un
throw error
incorrect
or missing
visibility
y devolvemos
el
visibility
from request
con todo esto
lo que nos estamos asegurando
básicamente
esto
no sé por qué pasa
a veces
el irregular
white spaces
pero me pone los nervios
¿sabes?
porque dices
¿pero de dónde sale
ese white space?
bueno
lo que hemos conseguido
con esto ya
es parsear
es validar
en runtime
y parsear
todos los datos
de forma que ahora
nos hemos asegurado
que el contrato
que tenemos en TypeScript
pase lo que nos pase
el usuario
desde fuera
¿vale?
no va a ser
lo que le dé la gana
sino que va a ser
lo que nosotros
controlamos
y ahora sí que no nos va a colar
cualquier cosa
ahora puede venir aquí
puede decirme
voy al Thunder Client
le voy a dar un post
voy a meterte por aquí
un day true
y a ver lo que pasa
pues haz lo que pasa
que no me da la gana
y entonces
pues bueno
un connection refuse
porque nos ha dado
un error 400
básicamente
bueno
espérate
espérate
que aquí en la terminal
no nos está compilando
espérate
vamos a ver qué ha pasado aquí
no puede encontrar
ah vale
espérate
claro
espérate
hemos hecho todo este trabajo
yo aquí
súper contento
y este
to new diary
no lo estoy importando
digo yo
que lo tenemos que importar
ya que lo hemos hecho
¿no?
venga
ahora sí
to new diary
restarting
bueno vamos a ver
qué problema tiene
no puede encontrar types
vale vale
ahora está tirando esto del hilo
y no está encontrando las cosas
bueno
vamos a ver
no puede encontrar types
¿dónde lo puedes encontrar?
en diaries.ts
¿no puede encontrar types?
a ver
¿dónde está este types
que no puede encontrar?
aquí no lo tenemos
en diaries
aquí no estamos utilizando
los types
a ver
según esto
si miramos
es en roots
diaries
es aquí
ah vale
porque
ah pues no
pensaba que
que estábamos utilizando ahí
pero no veo
que esté utilizando
a ver
¿dónde se me ha colado este?
en utils
o sea dice que es en utils
que no puede encontrar los types
pues si está aquí
si estás ahí
no me engañes
a ver
el tsc
si compila
vale bueno
está dando otros errores
al menos
bueno
estos errores
estos errores
justamente
estos errores
vienen por este fichero
este diaries.ts
¿veis?
esto es lo que os comentaba antes
en la clase
que os decía
esto es que luego
nos puede dar
otro tipo de problemas
porque al crear
este tipo de estructura
de esta forma
ahora el enum
no debería funcionar
exactamente así
o sea
a lo mejor deberíamos poner
punto reining
¿sabes?
¿ves?
deberíamos utilizar
el enum
que hemos hecho
en lugar de utilizar
el string directamente
¿ves?
aquí es donde se podría utilizar
que os comentaba
pues esto luego
igual lo vemos
claro
deberías utilizar el enum
para asegurarte
si utilizas un string
al final es un contrato
demasiado débil
que esto puede cambiar
el día de mañana
aquí deberías utilizar
siempre el enum
que hemos creado
nunca deberías utilizar
un string
fíjate
pues por eso
esta estructura
que habíamos creado
que son los errores
que ahora me salen
en TypeScript
porque está detectando esto
me está diciendo
oye
que es que esto
aquí no utilices un string
porque esto tienes que utilizar
aquí un enum
entonces te obliga
a que sea bueno
y te haga todo esto
¿vale?
como esto
no lo debemos utilizar
pero bueno
ha sido interesante
porque así veis este ejemplo
porque ya no podíamos
utilizar los strings
pues nada
hacemos un delete
y al menos
no vamos a quitar
los errores
esos que no sé por qué
salía
ves ahora ha compilado
pero lo que no sé
es por qué no funciona
el otro
el run dev
no sé
es que dice
que no encuentra este
ves
types
no sé qué
pero este
viene de aquí
de este
viene de este
ves
se vuelve
tarumba
parece
no sé si es que es algún
tipo de
de caché
o lo que sea
bueno
por ahora mira
lo voy a compilar
porque como es lo último
así que
que se supone que deberíamos
node
build
index
js
bueno
en pm start
debería funcionar
ah mira
fíjate
esto
ah
no
es que me lo está dejando
a ver
voy a leeros
que seguro que habéis
encontrado algo
será por el dts
sí
sí
a ver
d
dts
sí
es súper raro
a ver
es en el utils
vamos a darle aquí
no pero es el
este
me
lo estamos importando
aquí en este
vamos a poner punto d
a ver
a ver si le gusta más
súper raro
porque en otros id
si lo estamos importando
así
no
to require fire
make sure
espérate
a ver si en el dts
he hecho algo
que no esté bien
a ver si le ha liado
no pero el utils
está en la misma carpeta
utils.ts
aquí está igual
a ver
dice
this is the result
of a faulty configuration
or import
make sure
this is a js
or json
a ver si he puesto un js
por ahí
me he quedado a gusto
y los enum
los enum
creo que están bien
también
a ver
no los enum
van con coma
los enum van con coma
o sea
es que además
se quejaría esto
ves
esto se quejaría
y me diría
no no
esto no lo puedes hacer
hasta aquí esto está bien
lo que no entiendo
es el utils
está claro
que se me está quejando
pero fíjate que incluso
si hago esto
me lo importa correctamente
y me lo está encontrando bien
aquí me lo está encontrando bien
no me está dando ningún problema
o sea que es bastante raro
faulty configuration
or other executors
with loader
a ver vamos a ver el error
un error to require file
source types
dts
source types
dts
y el export
lo he puesto
export enum
export
export interface
esto lo voy a eliminar
pero bueno ya es tú
sí sí
cannot find
model.types
y el punto barra types
esto lo estamos haciendo
tanto
lo estamos haciendo aquí
eso lo estamos haciendo aquí
weather visibility
a ver aquí no tiene nada raro
hostia que es súper raro
a ver está claro
que algo le pasa al enum este
que no le gusta
quita el d.td
a solo ts
pero si no
el d.td
no lo tengo
ves
y es que no se puede poner eso
o sea
hay que ponerlo así
el d
el punto d es un error
sí el punto d es un error
o sea esto no
no debería ser así
por eso
pero no tengo ningún sitio
punto d
que yo encuentre
vaya
que yo encuentre
past dot object
hostia
esto
en el
el utils
es .js
vale
vale
pues ya está
no
no
es .ts
a ver
este error
si fuese .gs
.js
sí que es normal
que estaría petando
pero
ya veo
veis que no
aquí pone
utils .ts
tienes un archivo
types .ts
pasalo a types .ts
no pero
vale ya está
es verdad
jp
mallorga
la ha dado
ese es el problema
de hecho se me ha olvidado
claro
ahí está el tema
que debería ser así
ahí está
ahí creo que está el tema
ahí está
¿por qué?
¿por qué es esto?
muy bien
oh
galop
perdón
es que a ver
es que si escribís
lo que tenéis que hacer
en lugar de escribir mucho
es escribir
una frase
pero que diga
claramente
porque claro
es que como escribís mucho
pero con súper corto
pensad que yo
lo voy leyendo
y digo
pero qué leches
bueno
muchas gracias
por haberos dado cuenta
sí se me ha colado
a ver
el problema que tiene
y es que
mira que lo sabía
que me iba a pasar
y hostia
ahora me estaba cayendo
el tema es
que cuando hacías
el .d
.ts
eso son las definiciones
y el tema es que ahora
como hemos hecho esto
esto ahora es
como he dicho
es código
que sí que vas a poder utilizar
¿ok?
entonces
esto sí que se convierte
en javascript
si lo buscamos
de hecho ahora lo vamos a buscar aquí
cuando lo he hecho
es que justo lo quería compilar
para esto
para que viésemos en el build
y en el build
ahora en el types.js
¿veis que yo os decía
que os transformaba
esta estructura
este num
en algo que podáis utilizar?
porque lo tenemos ahora aquí
lo que teníamos antes
el type
de hecho yo si lo pongo aquí
voy a inventar otro
¿vale?
voy a poner un export
type
twitch
y le ponemos que esto es
midu
chat
muchos
mensajes
aquí
te lo dije
¿vale?
pues este
entonces este
lo que pasa
este twitch
si yo ahora lo busco
en los types
no está
¿vale?
ese type
desaparece
no es lo mismo
con los enums
que sí que se quedan aquí
el problema
que estaba viendo
es que el types.d.ts
es para las definiciones
en cuanto ya le pones enums
y tal
claro
esto
ese d
de definiciones
ya no lo puedes utilizar
ahora tienes que pasar
a types.ts
o lo podríamos separar
¿vale?
que eso podría ser otra
podrías tener
types.d.ts
que podría tener
todo sentido en el mundo
de hecho
puede ser mejor
el hecho de tener
el types.d.ts
y a lo mejor
tener
en otro sitio
pues
enums.ts
¿no?
los enums
los sacamos aquí
es que de hecho
esto es una cosa
que quería hacer
y al final lo hice
pues tenerlos aquí
que tú los exportas
estos enums
los importan
donde los necesites
por ejemplo
estos dos sitios
pues haces el import
aquí de los enums
¿vale?
y aquí
pues importas
pues lo mismo
from
enums
y los utilizas
y ya está
y de esta forma
te quitas un poco
esta mezcla
que es un poco rara
¿ves?
ahora funciona correctamente
justamente lo que queríamos
y ahora
ahora sí
ahora sí
si vamos al thunder
y le digo
no te quiero colar
este headers
este body
con esta información
de aquí
que sé que es mentira
que no funciona
¿vale?
pues ves
la fecha
oye que la fecha está mal
ah bueno perdona
yo lo he intentado
vale pues a ver ahora
¿no?
y ahora pues no
ahora lo que está mal
es el weather
¿por qué?
porque Kikos
pues no es un weather
que yo acepte
ah vale pues toma Sunny
pues no
ahora la visibilidad
hostia la visibilidad
pues ok
y hasta que no me da
lo que necesito
pues no me da la gana
que meta esa información
así que ten en cuenta eso
typescript
estático
para ti
pues sí
pero no te hace
ningún tipo
de chequeo
en room time
ni de los datos
que va a introducir
el cliente
ni nada de esto
¿vale?
esto muchas veces
a la gente se le
se le cuela
y se vuelve un poco loca
luego
nosotros hemos hecho
¿por qué hemos hecho
todo esto manual?
¿no?
porque a lo mejor
ahora dice
oye pero no hay unas
no hay mejores formas
de validar
este tipo de
de información
porque has hecho
todas estas validaciones
aquí en el YouTube
a ver
lo hemos hecho
nosotros
todo a mano
porque quería
que vieseis
todo el tema
de parseo
todos los temas
estos de
de validación
de mirar
si es un string
y todo
hay un montón
de herramientas
que ya te hacen
este tipo de validaciones
¿vale?
y que no tienes
que escribir
todo esto
porque ya lo hace
ya está hecho
si es un string
no sé qué
y además
de forma incluso
mucho más declarativa
¿no?
hay un MyDewerde Express
que es bastante famoso
que también te lo puede hacer
que a lo mejor
no te hace tanto
la
la
la transformación
pero sí que te puede
hacer pues temas
¿ves?
te hace la validación
y te da errores
yo recomendaría
seguramente utilizar
algo así
porque además
los errores
son un poquito más
es mejor
pero bueno
aquí tenéis
sanitation
¿no?
para normalizar
ciertas cosas
escapar cosas
está bastante bien
yo recomendaría
utilizar más esto
pero no lo hemos utilizado
porque estamos
enfocados en TypeScript
¿vale?
no estamos enfocados
en la parte de Express
sino la de TypeScript
y quería que vieseis
cómo hacer todo esto
por vosotros mismos
porque me parece
muy interesante
y veis todo el tema
del casteo este de
ah pero ver esto
si es un string
y cómo miro desde un any
¿no?
y cómo mirarlo
y cómo no sé qué
y cómo lo transformo
bueno
para que lo sepáis
¿vale?
y cómo se puede hacer
en TypeScript
totalmente
todo
y cómo es posible
pasar de un objeto
que es un any
¿sabes?
porque no podemos controlar
lo que nos está devolviendo
el usuario
¿cómo podemos asegurarnos
que lo pasamos
a un tipo de dato
que es compatible
con lo de TypeScript?
a partir de un any
hemos transformado ahí
justamente
el tema de
de tener un objeto
super tipado
así que bueno
ese era el tema
no sé
¿qué os ha parecido?
¿os ha gustado?
no he parado de hablar
¿eh?
o sea
así un pla pla pla pla
pim pam pum
¿sabes cómo me siento?
me siento
cuando he terminado
ha sido como
¿vas a subir las clases
a YouTube?
claro que sí
cuenta con ello
¿no te da sed?
hostia sí
sí que me da sed