This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Bueno, aunque los genéricos son compatibles con mucho lenguaje de programación,
no están disponibles en JavaScript.
Es una cosa que es solo de TypeScript.
Así que vamos a desvelar los misterios de los genéricos
y a ver cómo los podemos agregar.
Venga, introducción a los genéricos.
En los módulos anteriores hemos aprendido a aplicar anotaciones
de tipo de las interfaces, funciones y clases
para crear componentes fuertemente tipados.
Componentes, bueno, clases, funciones, componentes...
Todavía no hemos llegado a riar, pero lo veremos.
¿Qué ocurre si quieres crear un componente que funcione
con una variedad de tipos en lugar de solo uno?
¿Esto qué significa?
Pues que tú tengas un método que pueda recibir diferentes tipos,
pero todavía no sepas cuál puede ser y cómo se tendría que comportar.
Claro, puedes utilizar el eni, que esto sería cualquier tipo,
pero esto no es lo que queremos hacer.
Así que vamos a ver cómo aprovechar esto de la sistema de comprobación de tipos,
el tema de los genéricos.
Los genéricos son plantillas de código que puede definir y reutilizar
en código base.
Vale, no me gusta esta explicación.
Me parece una basura.
Yo lo voy a decir de otra forma.
Yo diría que los genéricos lo que son es pasarle por parámetros
los tipos que utiliza una función o lo que sea, o una clase o lo que sea.
Es como pasarle por parámetros qué tipo es el que tiene que utilizar.
Es que plantillas de código me parece un poco raro.
El hecho es cuando hablamos de funciones genéricas, se le habla genérica porque puede utilizarse
con diferentes tipos y tú le dices qué tipos son a los que se tiene que amoldar.
Por ejemplo, aquí tendríamos, ¿por qué usar genéricos?
Claro, tenemos este ejemplo, ¿no?
Tenemos esta función getArray.
Vamos a ponerla por aquí.
Esto lo voy a hacer.
Vamos a poner un nuevo playground aquí.
PlaygroundGenerics.ts.
Vamos a hacer esto un poquito más grande.
Lo podríamos poner en ZenMode, ¿no?
ZenMode.
Pam.
Vale, pues ya tenemos esta función.
Esta no es genérica todavía.
Vale, claro.
Aquí tenemos una función que dice getArray.
Que le pasamos como parámetro los items y le decimos que es un array de cualquier cosa.
Claro, pero esto si tú haces un getArray y de items le pasamos un array de string y de, por ejemplo, 1, 2, 3, esto funciona.
Porque le estamos pasando un array de cualquier cosa y esto se lo come con patatas.
Y aquí lo que dice es que devuelve un array de cualquier cosa, con elementos que son cualquier cosa.
Y entonces lo que devuelve es un array vacío concatenándole los items.
O sea, devuelve el mismo array que le estás pasando, pues lo devuelve como una copia de ello.
Pero veis, es este el problema.
El problema es que aquí lo que estamos haciendo es que, como hemos dicho any,
imagínate que yo solo me gustaría que fuese un array solo de números o solo de string.
En este caso no funciona correctamente.
Entonces, aquí no estamos controlando muy bien el tema de la función.
O sea, estamos poniendo any y por lo tanto se come cualquier cosa, ¿verdad?
Vamos a ver...
Uy, ¿qué pasa aquí?
Esto es que se me ha puesto...
Cuando he puesto el ZenMode...
Ah, ¿cuándo pongo el ZenMode?
Ah, no sabía que se ponía ZenMode.
Es que...
Vale.
Vale.
Entonces, claro, imaginad que nos gustaría tener esto, ¿no?
Un array de números, un array de strings y que podamos de alguna forma comprobar que
solo es ese tipo.
Pero claro, si decimos any no podemos hacer esa distinción.
Vamos a copiarlo por aquí.
O sea, si yo hago esto por aquí, hago number, voy a poner la función arriba, ¿vale?
Aquí.
Claro, tenemos un number array y yo lo que esperaría es que este number array siempre fuese de números el array.
Entonces, si yo hago un number array y hago un push y ya le pongo aquí midu, pues ya la he liado.
Porque este number array, pues es un array ahora de números y de un string.
Y no estoy haciendo ningún tipo de control.
Para solucionar esto, ¿veis?
Aquí sería con un número, con strings.
Al final, el tema es que se lo come todo.
¿Veis?
Ok, ok, ok.
Se lo come todo con patatas.
Entonces, es que es lo malo de utilizar el any.
Pero, ¿qué pasa?
Y a ver, puede tener sentido esto, ¿eh?
Esto no está mal.
Esto lo que significa, lo único que tienes que tener en cuenta, es que al poner any, tú puedes poner aquí lo que quieras.
O sea, hemos hecho un push de midu, como que puedo hacer en el number array, pues hacer un push de un objeto, por ejemplo.
Y esto se lo come, y se...
Claro, o sea, puede estar bien, pero tenlo en cuenta, solo eso.
Imagínate que no queremos que ocurra esto.
Queremos que los arrays que estamos creando siempre sean de un tipo, ¿vale?
¿Qué ocurre si quieres especificar el tipo de los valores que contendrá la matriz cuando llaman la función?
Para hacer eso, tenemos que entender esto, ¿vale?
Vamos a ver cómo funciona esto.
Vamos a comentar el anterior.
Esto es bastante diferente, ¿vale?
Lo que está haciendo aquí, mira, de hecho es que ya peta de gratis.
Y fíjate que no hemos hecho ningún cambio.
Lo que significa esto, la función getArray, lo que estamos diciéndole aquí, es que es un tipo que le llega como por parámetro o que lo va a inferir.
Inferir significa que va a detectar qué tipo es, ¿vale?
En lugar de poner aquí el tipo que es, estamos utilizando siempre la t.
O sea, es como que nos estamos refiriendo a un tipo que todavía en esta declaración no sabemos qué tipo es.
Esto podría ser un number, podría ser un string, podría ser lo que fuese.
Así que estamos utilizando esta t como que el tipo que sea es el que tiene que ser el array, tiene que ser siempre de este tipo y va a devolver un array de este tipo.
Esto que le ha puesto una t, esto se podría llamar de mil formas.
Podría, por ejemplo, elements of array type, podría ser, ¿no?
Pero entonces ahora siempre tendríamos que cambiar esto, ¿vale?
Tendríamos que siempre llamarle así.
Esto es muy verboso y por eso normalmente, como cuando es un tipo, me supongo que dicen, bueno, vamos a utilizar solo la t.
Si ya viene el siguiente, creo que ya es a partir ese, no sé si la u y cosas así.
No sé, la verdad que no soy un gran experto en esto.
Ya lo iremos averiguando.
Creo que es la u, si no me equivoco.
La v no, porque la v suele significar value.
Entonces no sé su utilizar.
Pero la t, se utiliza t por type.
Pero ya veis que esto es un parámetro que lo podéis nombrar como le os dé la gana, ¿vale?
Le podéis poner el nombre que queráis.
Así que, lo que os dé la gana.
Vale.
En este caso, ¿por qué funciona?
Pues porque cuando hacemos este getArray, lo que está pasando es que TypeScript está siendo capaz de determinar que el array que le estás pasando es de números.
Por lo tanto, este numberArray, cuando ya está diciendo que devuelve esta t, sabe que es de números.
¿Veis?
Este numberArray, fíjate que ya sabe que es de números.
Esto es la magia que tiene TypeScript, que es una pasada, ¿vale?
Entonces, cuando en el numberArray le intentas pushear un string, te dice, no, es que el tipo string nos hace un number al tipo number.
Porque ya sabe que es un array de números.
Porque lo ha inferido.
Pero también, si no, le podríamos decir nosotros el tipo que lo podríamos forzar.
¿Vale?
De hecho, sería tan fácil.
Aquí en el getArray, igual que aquí, para ejecutar la función, lo ponemos ante paréntesis, podríamos poner aquí, pasarle, pues por ejemplo, decirle que esto es de number.
¿Vale?
Esto funcionaría igual porque ya os digo que esto lo está calculando exactamente igual, ¿vale?
O sea, es lo mismo.
No estamos haciendo nada diferente.
Pero, bueno, aquí sería de string.
¿Vale?
Pero esto ya lo está calculando TypeScript sin necesidad.
El problema es que aquí pusiéramos number.
Entonces, sí que la liamos.
¿Veis?
Dice, oye, que me está pasando strings y me está diciendo que esto es del tipo number.
Entonces, el array de números debería ser, no sé qué, vale.
Esto también eso lo podríamos pasar así.
Pero fíjate que es como pasarle por parámetro el tipo que tiene que utilizar aquí.
Entonces, aquí, en esta primera línea, si ponemos aquí string, pues significa que esto será string, esto será string, esto será string.
Siempre donde se vea la T, pues será un string.
Ya está.
Eso sería, ¿vale?
No sé si queda claro, pero es una de las gracias que tiene el tema de los genéricos.
Vale, vamos a seguir leyendo.
Vale, aquí sería que está array number, ¿ves?
Y ahora sí que petaría cuando intentas pushear un string, que es lo que hemos visto.
Uso de variables, de varias variables de tipo.
Vale, mira, con la U.
Vale, imagina que tenemos la función identity.
Claro, esto hemos visto aquí que estamos haciendo un solo tipo.
Pero esto puedes tener varios tipos.
O sea, aquí podrías empezar a tener la U, la S, ¿vale?
Podrías tener más de un tipo.
Ya sería, se complicaría bastante.
Habría que intentar evitarlo, pero puede ocurrir, ¿vale?
Y aquí lo vamos a ver, justamente.
Una función identity que recibe dos tipos por parámetro y recibe dos parámetros.
El value, que es del tipo T, y el message, que es del tipo U, y devuelve un tipo T, ¿vale?
O sea, importante, el primer parámetro, que es value, y lo que devuelve la función son del mismo tipo, ¿vale?
Porque es T.
Así que esto, vamos a ponerlo ahora en nuestro... aquí, ¿vale?
Y ahora, identity, pues lo podríamos ejecutar como hemos hecho antes, ¿vale?
Podríamos poner identity que fuese un string, hola, y podríamos poner que la U fuese mensaje, ¿vale?
Y esto funcionaría bien porque lo que está haciendo esto es entender, ¿ves?
Que los dos que le estás pasando, pues son strings y ya está, ¿no?
Eso podría ser, y esto lo podríamos guardar, de hecho, aquí en el...
Podríamos guardar el value y ya estaría, ¿vale?
Y el value, pues nos dice que el valor es hola.
En este caso, ¿veis?
No ha detectado que sea un string.
Lo que ha detectado es que es hola directamente.
No nos está diciendo el tipo del parámetro.
Interesante.
Pero si no, lo podríamos forzar, ¿eh?
Decimos que ese es un string y es un string.
Pues ya está, ¿ves?
String y string.
Entonces, value es un string.
Ya está.
Claro, si esto mismo lo intentásemos hacer así, pues number, number, pues esto lo que significa es que el parámetro, ¿ves?
Espera dos argumentos, ¿vale?
El primer argumento tiene que ser un número.
Si ahora le pongo hola, pues me va a apretar.
Y si le pongo mensaje aquí también me va a apretar, ¿vale?
¿Veis?
Me está diciendo ya que el argumento tipo string, no sé qué.
O sea, nosotros somos los que estamos controlando el tipo que tiene que controlar.
O sea, el tipo que necesita la función.
Es como pasarle los tipos por parámetro.
Básicamente es eso.
Ya está.
Vale.
Bueno, claro.
Y luego, una vez que ya tienes ese tipo, pues ya no te lo puedes asignar tampoco.
Porque si tú le dices que esto devuelve t, y aquí le estamos diciendo que t es lo mismo que el primer parámetro,
y le decimos que es un string, este value ya no podría hacer value por 10.
¿Por qué?
Si aquí pongo result de esto, ¿ves?
Me dice que la parte a la izquierda de una operación numérica tiene que ser del tipo any, number, begin, pero no string.
Y en este caso es string, por eso lo estoy poniendo aquí.
Al final el tema de los tipos de TypeScript es que hay que tener en cuenta que una vez que empiezas,
eso ya es una cadena de cosas que no puedes parar.
Es una bola.
Es una bola.
Uso de los métodos y las propiedades de un tipo genérico.
Vale.
Vamos a ver.
Function identity.
Esta es nuestra función.
Ah, esto yo creo que es lo peor de los genéricos.
Claro, esto es algo parecido a lo último que hemos hecho.
Mira, vamos a verlo aquí.
Vamos a verlo aquí.
Este cambio, fíjate que el cambio que está ocurriendo aquí es que ahora está haciendo una suma.
Aquí.
Claro, como value, ahora ves, el operador más no puede ser aplicado a tipos T.
¿Por qué?
Porque T puede ser cualquier cosa.
Por lo tanto podría ser un string, por ejemplo.
Podría ser, yo que sé, un objeto.
Entonces, ves que te dice esta operación aritmética, pues no se puede hacer.
Esto se puede controlar.
O sea, tú puedes empezar a hacer restricciones.
Por ejemplo, aunque tú le pases el tipo por parámetro, lo que podemos hacer es un tipo
de este estilo y tener aquí esto como era una, no recuerdo cómo se llamaba esto, una, joder, no me sale el nombre.
Ah, una tupla, es una tupla.
Yo iba a decir un or, pero no es un or, es una tupla, ¿vale?
Esto era una tupla.
Entonces, podemos decirle los tipos válidos, valid types y tenemos esta tupla que puede ser string o number.
Pero bueno, espérate que esto todavía tiene historia.
Porque le podemos decir, veis que dice T extends valid types.
A mí esto es lo que más suele ser un poco rollo, porque empieza, veis que empieza a llenar un montón
la función con un montón de historias.
A ver, el único sitio donde tienes que decirle qué podría ser T sería aquí, ¿vale?
Hay otra forma de hacerlo, pero bueno, ahora vamos a ver esta, que sería decirle la T tiene que ser
un string o un number, porque valid types lo tenemos aquí.
Entonces, sería un string o un number.
Así que, si le decimos aquí que extends de valid types puede ser un string o un number.
Pero esto no nos soluciona el problema, ¿eh?
No te creas. ¿Por qué?
Porque si decimos que puede ser un string un number, pues este value más value.
En este caso, igual tenemos que decirle que puede ser un number o puede ser, ¿qué podría ser?
A ver, ¿qué dice aquí?
Que resolve no puede ser, ¿eh?
A la tipo T.
Ah, pues pensaba que de aquí...
Claro, porque es que aquí le estamos diciendo que puede ser...
Igual deberíamos decir que esto no sé qué, pero claro, entonces ya no puede ser T otra vez.
Bueno, esto tiene arreglo.
No, aunque sea un string, tiene arreglo.
Lo que pasa es que aquí ya se mezcla la compilación con el runtime.
Luego, supongo que luego lo explicarán, ¿vale?
Pero bueno, por ahora, veis que aquí sigue dando este error.
Este error, que en realidad, claro, una vez que tenemos esto de string number y tal,
esto me imagino que si lo utilizamos, identity, y le decimos que identity, el valor, el primero es un number y el segundo es un string, ¿vale?
Y lo ejecutamos y le decimos que esto es uno y esto es hola.
Claro, aquí no nos da ningún problema y esto sí que debería funcionar.
Pero bueno, el problema está más dentro de la propia función.
Esto no funcionaría.
En TypeScript no lo compilaría.
Vale, dice, también puede restringir un tipo a la propiedad.
Esto supongo que lo van a explicar.
¿Veis?
Aquí lo van a explicar un poco más abajo.
Vale.
Ya sé que ahora lo retomaremos.
De hecho, igual, vamos a saltarnos este y seguimos con este, porque me parece más interesante.
¿Qué pasa con este valid types?
¿Cómo solucionamos esa suma y tal?
Esto es uno de los típicos problemas, que además es que esto te fastidia la mente, porque es muy raro.
Mira, tenemos el valid types.
Esto es lo que tenemos en nuestro ejemplo.
Y tenemos la función identity con el tipo t, que extiende valid types, por lo tanto tiene que ser string o number, ¿no?
El value, el primer parámetro es la t, message es una u.
Aunque aquí no ha puesto el tipo que está devolviendo.
O sea, aquí ya está diferenciando, aquí ya no está poniendo esto.
Bueno, para empezar.
Pero, además, ve, el resultado es uno de los valid types.
Aquí ya me extraña que le está poniendo un string directamente.
Pero bueno, vamos a verlo.
¿Veis que está guardando aquí en el resultado?
En lugar de hacer esto ya directamente, está diciendo, no, esto es un valid type y ya le está poniendo aquí que sea un string.
Como puede ser un string o un number, ¿vale?
Pues ya está haciendo esto.
Entonces, ¿cómo hace la suma?
Ostras, pues fíjate en el código, ¿vale?
Bueno, este type value, no sé para qué lo utiliza.
Ah, va, para aquí.
Esta línea no tiene sentido.
Es esta.
Esta línea es la que es muy rara, ¿vale?
Porque fíjate que hace exactamente lo mismo las dos.
Es muy raro, ¿no?
Esto lo vimos en una clase anterior.
Lo que está mirando es que si, aquí, está utilizando un runtime.
Si el type of de value es igual a number, entonces el resultado es value más value, ¿vale?
Pero si el type of de value es un string, entonces el resultado es value más value.
Y esto funciona.
Y esto funciona.
¿What?
¿Cómo?
¿Cómo?
Esto sí que funciona y, en cambio, lo que habíamos hecho antes de result igual value más value, no funcionaba.
Y fíjate que sigue sin funcionar.
Porque nos dice que el operador más no puede ser aplicado a tipos T.
Es súper raro esto.
Esto es una de las cosas que cuando trabajas con genéricos y tal, es un poco rollo.
Fíjate que aquí hace lo mismo.
Pero claro, ¿cuál es la explicación de esto?
Es que, en realidad, aunque se vean igual las dos líneas, no hacen exactamente lo mismo, ¿vale?
Es muy raro.
Pero es que no hacen lo mismo.
Este está haciendo una suma y este está haciendo una concatenación.
Entonces, TypeScript, para poder funcionar en su mundo de tipos y tal,
tiene que diferenciar estas dos operaciones de alguna forma porque dan resultados distintos.
Uno da un string, otro da un número.
Y en este punto en el que resulta, además, puede ser un string o un número,
tendría que saber exactamente qué es lo que va a pasar.
Y claro, TypeScript no se ejecuta en runtime, tened en cuenta eso.
Solo en compilación.
Por lo tanto, este código es el que le ayuda a diferenciarlo.
Bueno, no sé si os estoy dando la chapa con esto,
pero es que esto me parece súper, súper, súper, súper importante.
Súper importante y súper interesante.
Y es una de las cosas que más cuestan cuando se trabaja con genéricos, ¿vale?
Entonces, bueno, esa sería una forma de arreglarlo.
Por supuesto, nada, al identity, pues veis que aquí le podríamos seguir pasando lo que queramos.
De hecho, ahora podríamos pasarle también un string y esto debería funcionar.
¿Vale?
Uno, uno y tal.
Vale.
Venga, vamos a continuar.
Ah, sí, esto es importante.
La restricción de tipos, de type of, solo sirve para comprobar tipos primitivos.
String, number, begin, function, boolean, symbol, object.
¿Vale?
Para las clases tiene que ser instance of.
Venga, ejercicio.
Implementación de genéricos con interfaces y clases.
¡Buah!
Vale, declaración de una interfaz.
Declara una interfaz denominada identity que tenga dos propiedades, value y message, y dos variables de tipo genérico T y U.
Bueno, esto debería ser interface, y ha dicho que se llama identity.
Pues esto sería T, U, ¿no?
Y aquí value, y le decimos que esto es T, y message, y esto le decimos que es U.
¿Vale?
Pues esto debería, no sé si la coma, creo que sobra.
¿Vale?
Ya teníamos nuestra interfaz.
¿Vale?
Ah, mira, con punto y coma.
Yo cuando coma.
¿Vale?
Lo he hecho bien, ¿no?
Sí.
Declaré dos variables utilizando la interfaz identity como un tipo objeto.
¿Vale?
Porque como tenemos una interfaz, pues lo que podemos hacer es identity, y le diríamos que esto es un identity.
Solo que ahora le pasamos como por parámetro el tipo, ¿vale?
Le decimos que la T, pues por ejemplo, que sea number, y lo otro sea un string.
Y con esto ya podríamos crear nuestro objeto, que value sea uno y message sea, ¿vale?
Pero esto mismo lo podríamos hacer, por ejemplo, con un string y un string, ¿no?
Y el value, pues puede ser uno.
O lo podemos hacer con number y number.
Bueno, en realidad lo podríamos hacer con casi cualquier cosa, ¿no?
Podríamos poner aquí vol, volean, y volean.
A ver, que no tiene mucho sentido hacer esto.
Pero que es un poco para que veáis la gracia de los genéricos, ¿vale?
O podríamos limitar el tipo de los genéricos.
Pero bueno, que aquí ya tendríamos...
Aquí creo que se ve bastante bien el tema de la magia esta que tiene el tema de los genéricos.
Pensad que un genérico muy típico es el propio array.
El propio array es un genérico, ¿no?
Porque aquí lo que hacemos es array y le podemos pasar el number, ¿no?
Claro, pues esto...
Esto en realidad sería como un genérico, pues le estamos diciendo al array el tipo que tiene.
Sería una especie de genérico.
Para que más o menos os hagáis a la idea.
Vamos a ver qué más nos cuenta.
Declaré dos variables.
Estamos hechos.
Declaración de interfaz genérica como un tipo de función.
¿Vale?
Seguimos.
Declaré una interfaz genérica denominada Process Identity que incluye la asignatura genérica de un método.
¿Vale?
Pues venga, vamos a ello.
La interfaz Process Tal Identity que nos dice que la genérico es de un método.
Value t, message...
¿Pues es que ya lo pone aquí?
Value message.
Entonces sería la t y la u.
Y aquí tendríamos el método.
¿Vale?
El método tiene que ser paréntesis.
Value es del tipo t, message del tipo u.
Y ahora me imagino que nos van a decir que hagamos lo mismo, ¿no?
Process Identity.
Y vamos a decir que el tipo t es number, este es un string.
Y Process Identity y tal.
Y ahora esto podría ser una función que se le pasa en el value, en el number.
¿Vale?
Es un poco más...
Bueno.
Ahora no sé qué deberíamos hacer Process Identity, pero podríamos hacer un console.log del message.
Y devolver el value.
Claro.
Tiene que ser devolver el value.
Bueno.
No tiene por qué ser devolver el value.
Pero, como tiene que ser del mismo tipo, porque en la firma nos lo ha dicho, ¿no?
El primer parámetro es t y lo que devuelve es algo que también es del tipo t.
Aquí en este caso lo más fácil sería hacer un return value, que es lo mismo y sabemos que es del mismo tipo.
Pero fíjate que aquí ya estoy creando una función que de alguna forma estoy obligando que el Process Identity,
que estoy utilizando el tipo de esta función, el tipo de number, o sea, el primer tipo t es number.
Por lo tanto, yo cuando el Process lo use, tengo que pasarle aquí ya un 1 y aquí un hola, por ejemplo.
Si aquí ya le paso un string, pues ya se va a quejar.
¿Vale?
Es como que aquí ya no puedo...
Una vez que tú has creado una función que tienes el tipo y le estás indicando el tipo que es,
ya no puedes cambiarlo.
¿Vale?
¿Vale?
¿Vale?
Mira, justamente esto lo que he hecho.
Declaro una función llamada...
Justo, o sea, he hecho lo mismo.
Declaro una variable del tipo de función de moneda del Processor.
¿Vale?
Process Identity.
¿Vale?
Bueno, claro, esto es interesante.
A ver.
A ver, es un poco de tontería, pero...
El tema es que yo es que he hecho las dos cosas a la vez.
¿Veis?
Que yo he hecho...
He creado la función y ya la...
Le he puesto al tipo y aquí he creado la función directamente.
También se podría hacer de otra forma.
O sea, se podría crear la función, decir que esto es ValueNumberMessageString,
que esto devuelve, por ejemplo, un number.
Crear aquí otra función que hace lo mismo, ¿eh?
Pero es un poco para que veáis que se podría hacer de otra forma.
Claro.
Y esto sería una función, digamos, que no está siguiendo todavía la interfaz esta,
pero podríamos, una vez que creemos otra variable,
ProcessorWithInterface o UsainInterface,
ya le podríamos decir que estamos utilizando esta
y que tiene que ser con number y tiene que ser con string
y asignarle justamente la misma variable, o sea, la misma función.
A ver, son dos formas distintas de hacerlo.
Yo me quedaría con la primera.
El ejemplo que están poniendo es un poco recambolesco.
Es lo mismo, solo que en lugar de poner aquí
que estás utilizando esta interfaz,
estás creando que toda la función tenga, pues, el number, el string,
o sea, todo el contrato de los parámetros y lo que devuelve,
y luego le dices lo que la interfaz que tiene que cumplir.
No sé, me parece un poco raro.
Un poco raro, la verdad.
No sé.
No me parece.
Yo me quedaría con lo de arriba, ¿eh?
En mi cabeza.
Estoy pensando cuando puede tener sentido la otra, pero...
A ver, puede tener sentido cuando esto, claro,
en este caso,
cuando no le pones ningún tipo, ¿sabes?
Ni le dices que value es nada, claro,
y entonces, al crear ahora una,
sí que puedes ponerle el tipo
y le dices que te quedas process.
Ahora sí que este procesor
sí que tiene que cumplir con estos tipos,
pese a que aquí no los tenía.
Así que, en process, claro,
tú le puedes pasar lo que te dé la gana.
¿Ves?
Pero a procesor ya no,
porque le has dicho justamente
qué es lo que tiene que controlar.
Claro, si yo le pongo string y string,
aquí, ¿ves?
Ya sí que se me queja.
Son diferentes, claro,
porque esta no tiene tipos.
Y esta sí que tiene tipos
y le hemos dicho a la interfaz
que tiene que cumplir.
Bueno.
Ok, ok.
Venga, vamos a seguir.
Vale, vale.
Declaración de una interfaz genérica
como un tipo de clase, vale.
Continúe trabajando en el área de juegos.
Declaro una interfaz
dominada processIdentity, vale.
Que tenga dos propiedades,
value y message,
y dos variables de tipo genérico.
Vale, vamos a poner.
Claro, esto lo hacen
para que repitas constantemente
un poco, ¿vale?
Propiedad value.
Value, que va a ser tipo t.
Message tipo u.
Y dice que tenemos que tener
un método llamado process
que devuelva la t.
Vale.
La t.
Ya tendríamos esto.
Y ahora nos dice
Defina una clase genérica
denominada processIdentity.
Una clase genérica
que implemente la interfaz
processIdentity.
Hostia, una clase genérica
que implementa la interfaz.
O sea, tiene que ser
class processIdentity
con xy
que implemente
processIdentity
que esto también tendría que ser
con xy.
Claro.
¿No?
A ver, ¿qué dice?
Interface processIdentity.
Claro, todavía no lo hemos puesto.
Que implemente...
En este caso,
asigno a los tipos
la variable a los nombres xy.
Puedes usar nombres
de variable de diferentes
la interfaz y la clase
porque el valor del tipo
se propaga
y el nombre de la variable
no importa.
Claro.
Esto que quiere decir
es que cuando utilicemos
esta clase
y le pasemos aquí x,
este x se pasará
a processIdentity
y este x al final
será esta t.
y esta t pues será tal.
Cuando utilicemos esto
y digamos que esto es un string,
pues al final
la x será un string
y entonces la t será un string
y ya está.
Entiendo que value,
pues aquí deberíamos poner...
No sé si hace falta
que pongamos esto
o que creamos el constructor.
O sea, porque...
A ver.
Canofind name x.
Claro, esto tiene que ser x.
Message.
Tiene que ser y.
Y process...
Esto debería devolver x.
Y esto debería devolver,
por ejemplo,
this.value,
que ya sabemos que es x.
No sé si esto es lo que quieren exactamente.
No sé si necesitamos crear el constructor también.
Vamos a verlo.
Defino una clase...
Vale, sí.
Tiene constructor.
Vale, es un poco parecido a lo que he hecho,
solo que no he puesto constructor
porque a lo mejor decía...
Vale.
Constructor.
Para crear,
construir nuestra clase.
Le va a llegar por un lado
el value,
que esto tiene que ser de tipo x,
y el message,
que tiene que ser de tipo y.
Y esto,
this value,
sería value,
this message,
sería message.
Vale.
Y con esto ya lo tendríamos.
Ahora,
lo interesante es ir a ver
cómo lo utilizamos,
¿no?
En realidad.
Claro,
aquí ya tendríamos el process...
Ident...
Bueno,
process le voy a llamar,
¿vale?
Process identity.
Const process.
Y aquí,
¿ves?
Espera dos argumentos,
que es el value,
que vamos a poner que sea...
Pues no sé.
Vamos a poner primero pepito...
Bueno,
vamos a poner...
¡Hola,
Twitch!
Vale.
En realidad,
si nos fijamos...
Claro,
aquí ya puede inferir los datos.
¿Veis que ya ve que la x es string
y la y es string?
Cuando tú haces esto,
en realidad,
ya le estás diciendo de alguna forma,
le estás indicando de qué es cada tipo.
¿Sabes?
La x ahora es string.
Porque si aquí value es x
y en value le estoy pasando un string,
pues TypeScript dice...
Vale,
un string.
Entonces ya está haciendo el cálculo,
¿vale?
Y lo está pasando hacia abajo.
Pues la x es un string.
Process identity.
Le pasa un string.
Pues esto,
la t es un string.
El value un string.
¿Vale?
Eso es como que todo...
Al final lo infiere,
en este caso.
Que se podría...
Se le podría decir.
O sea,
al final se puede forzar.
Tú igual que haces aquí,
el new process identity.
Que le he puesto aquí...
Normalmente esto haría con mayúscula,
¿eh?
Pero como he puesto aquí la interfaz,
que sea con mayúscula también,
¿veis?
Le quejaría.
Normalmente habría que hacerlo con mayúscula.
Pero,
en este caso,
le podríamos decir,
no, no.
Yo creo que la x sea number
y la x sea boleano.
¿Vale?
Fíjate que ya se me queja.
Uy, ¿por qué?
Ah, bueno,
porque todavía no ha llegado.
¿Ves?
Aquí ahora tendría que ponerle uno
y ahora en el segundo me dicen,
no, es que las pasan en string.
Ah, no,
pues sería un true.
Esto es interesante.
¿Por qué?
Porque hay veces...
¿Por qué puede ser interesante,
¿no?
Porque alguien puede preguntar,
ostras,
pero ¿para qué le ponen los tipos?
¿No?
¿Para qué le ponen los tipos?
Si realmente...
O sea,
¿para qué haces esto,
¿no?
De que esto sea string,
string,
si ya cuando le pasas el parámetro,
en realidad ya sabes lo que es.
Por un montón de motivos.
Mira,
imagínate que esto,
tengamos aquí,
por ejemplo,
un resultado
y que si el math random
es mayor a 0,5
es hola
y si no es uno.
¿Vale?
Claro,
¿qué pasa con esto?
Que ahora el resultado
puede ser un número
o puede ser un string.
Al final,
normalmente lo que hacemos
es trabajar con variables.
Cuando creas una clase
o lo que sea,
lo que usamos son variables.
Entonces,
hay veces que ocurre esto
y a lo mejor tú te quieres,
quieres controlar
que realmente lo que te llega
es un string
o es un number
o es lo que sea.
¿Vale?
Entonces,
para eso es justamente
lo útil.
No porque
no sea capaz de inferirlo.
Es que inferirlo
lo va a hacer muy pocas veces.
¿Vale?
Porque muy pocas veces
tú le vas a pasar exactamente
lo que necesitas.
Así que por eso
se suele hacer esto.
Porque no siempre
es capaz de inferirlo
o lo infiere
y te puede llegar
a encontrar un error
y decirte
oye,
es que esto puede ser
string o number.
¿Vale?
Ah,
ostras,
pues no,
yo creo que sea un number.
Así que vamos a hacer algo
al respecto.
Vale,
bueno,
esto sería
con el process.
Claro,
se le podría asignar
en el value,
en el process este.
Vamos a poner aquí
que esto sea uno.
Hay que tener en cuenta
que esto,
bueno,
es que esto ya,
esto lo tenéis que tener controlado.
Si tú le dices
que aquí el value
es un number,
se lo pasas aquí
como un number,
pues luego no podrás hacer
process.value
y ponerle un string
porque ya se habrá quedado.
Definición de una clase genérica.
También puede declarar
una clase genérica
sin una interfaz.
Claro,
claro,
es que al final,
eso es lo que me estaba preguntando yo,
¿no?
Que era un poco raro.
Es que el hecho,
este implements al final
no nos añade nada.
¿Sabes?
Es que no añade nada.
Porque digamos que está duplicada
esta interfaz.
Por un lado la tenemos aquí
y por otro lado,
o sea,
es que no añade gran cosa.
A ver,
que sigue siendo genérica
una interfaz
puede tener sentido,
pero que en este caso
no sé,
es raro que lo expliquen
como al revés.
Pero,
¿veis?
O sea,
entre tener esto y esto,
al final,
esta interfaz del value
ya lo tienes aquí,
lo tienes aquí,
es exactamente lo mismo.
Otra cosa es que la interfaz,
por ejemplo,
pues en lugar de tener
lo que hemos visto antes,
en lugar de tener T y U,
pues esto es tienda
de un valid types,
no sé qué,
entonces sí que puede ser
más interesante.
Pero,
claro,
definición de la interfaz es genérica.
¿Vale?
Genéricos con tipos,
vamos a ver.
Madre mía,
con el estudio,
¿eh, Julio Burgos?
Todo.
Todo.
Perdón.