Generics en clases
Curso de TypeScript: Programación Orientada a Objetos y Asincronismo
Contenido del curso
Fundamentos de POO
POO Avanzada
Asincronismo y consumo de APIs
Genéricos
Próximos pasos
Generics en clases
Curso de TypeScript: Programación Orientada a Objetos y Asincronismo
Contenido del curso
Generics en clases
Carlos Eduardo Bracho Ramírez
EstudianteLiteral pasé las 2 clases preguntándome por qué esto era importante, hasta que la luz salvadora me iluminó en un instante de raciocinio, y comprendí la magnitud de Generics. Sencillamente, wow.
¿Esto serviría para crear un Backend completo con Node? Si alguien tiene un ejemplo, se lo agradecería.
Jaime Eduardo Falla Cardozo
EstudianteRealmente los genéricos nos puede ahorrar muchas líneas de código, son super poderosos si se implementan bien.
Angel Aponte
EstudianteImagina que tienes funciones que representa el CRUD de tu aplicación, pero puedes tener n cruds por cada módulo. Ahora teniendo esto en cuenta puedes reutilizar las funciones cambiando simplemente su alcance(entidad). Por ejemplo en tu aplicación tienes módulos para crear usuarios y productos. Que pasaría si los métodos de ambos módulos(los servicios) hicieran lo mismo?, aplicando esto puedes abstraer/separar lógica y reutilizarla para el orm siendo que los métodos siempre van a hacer lo mismo lo que cambia es tu entity.
Gabriel Hernández Valdez
EstudianteMi cerebro exploto, pero entendi muchas cosas con esta clase :D
Celso Espinoza
EstudianteVengo usando JS para el backend pero con esto pues no hay pierde. Me cambio a usar TS desde ahora. jeje
Alex Guaman
EstudianteTambien se puede escribir usando la convencion de nombres para genericos, que es comunmente con lo que te vas a topar
export class BaseHttpService<T> { constructor( private url: string ){} async getAll(): Promise<T[]> { const { data } = await axios.get<T[]>(this.url); return data; } }
Diego Raciel Ortega Hernandez
EstudianteLlevo dos horas intentando entender los genéricos. Hasta que me carburo el cerebro y por arte de magia lo entendí :0
Jhorman Salazar
EstudianteEste curso esta genial, Typescript es muy poderoso!. Ánimo chicos, no paremos de aprender!.
Jose Fabio Ortega Estrada
EstudianteCreo entender, usando la misma clase se hacen diferentes peticiones al servidor de diferentes entidades, lo que cambiaría es el tipado o genérico que le apliquemos a dicha clase, con esto se ahorraría la generación de una clase para cada entidad y varios métodos crud para cada entidad, lo cual ahorraría mucho en materia de líneas de código. Pero me surge una pregunta: ¿Hasta qué punto esto es beneficioso, ya que separar la lógica aparte de tener mayor claridad conserva el principio de una sola responsabilidad .? Si por alguna razon esta clase falla que sería la unica, fallaría toda la estructura relacionada con esa clase, por el contrario separando la lógica en diferentes clases mitigaría de cierta forma algún error que se presente en alguna clase especifica. Por otro lado las clases son representaciones abstractas del mundo real por ende cada entidad del mundo real, se representa como una clase por separado, entonces, se podría decir que separar las clases es algo mas cercano al mundo real. Entonces deben haber casos específicos donde se usen este tipo de genéricos . O NO, NO SE. solo son conjeturas mías, no soy experto. alguien que sepa mas que yo que me oriente por favor.
Odannys De la Cruz
EstudianteEstás en lo correcto, es buena práctica tener separado tus servicios por cada entidad.
Sin embargo, debes analizar tu caso específico. Si es algo pequeño entonces un genérico te ayudará mucho. Para proyecto grandes no se recomienda abusar de estos, no por la modularidad si no por mantenibilidad y por la extensibilidad.
Por otro lado los genéricos se crearon para poder tipar código reutilizable sin necesidad de usar el tipo any o tener que especificar todos los tipos que tendrá dicho código reutilizable.
Puedes ver mas aquí
David Higuera
EstudianteTambién se puede capturar el resultado de una promesa de este modo, para no hacer la función auto-invocada:
const url1 = "https://api.escuelajs.co/api/v1/products"; const productService = new BaseHttpService<Product>(url1); productService.getAll().then(console.log);
Ronaldo Delgado
EstudianteLos genéricos son lo mejor
Kevin Candia
EstudianteSería mucho mejor pasar la url en el método, y no el constructor, ya que si transformamos nuestro servicio a un singleton, la segunda instanacia del servicio, la url no la tomaría.
carlos orozco
Estudiante🤯🤯🤯
Felix Torres Javier Antonio
EstudianteParece que ya no sirve la api :/
Andre Huaman Yovera
EstudianteAquí tienes un ejemplo de cómo implementar el patrón Singleton en TypeScript para la clase BaseHttpService:
import axios from 'axios'; export class BaseHttpService<TypeClass> { private static instance: BaseHttpService<any>; private url: string; private constructor(url: string) { this.url = url; } public static getInstance<TypeClass>(url: string): BaseHttpService<TypeClass> { if (!BaseHttpService.instance) { BaseHttpService.instance = new BaseHttpService<TypeClass>(url); } return BaseHttpService.instance; } async getAll() { const { data } = await axios.get<TypeClass[]>(this.url); return data; } async update(id: string, changes: Partial<TypeClass>) { const { data } = await axios.put(`${this.url}/${id}`, changes); return data; } async create(dto: TypeClass) { const { data } = await axios.post(this.url, dto); return data; } async findOne(id: string) { const { data } = await axios.get(`${this.url}/${id}`); return data; } async delete(id: string) { const { data } = await axios.delete(`${this.url}/${id}`); return data; } }
En este ejemplo, hemos agregado un método estático llamado getInstance que se encarga de crear y mantener una única instancia de la clase BaseHttpService. El constructor de la clase es privado, lo que significa que no se puede acceder directamente a él desde fuera de la clase. Esto evita que se creen múltiples instancias de BaseHttpService y garantiza que siempre se utilice la misma instancia en todo el código.
.
Ahora, veamos por qué es bueno utilizar el patrón Singleton:
Garantiza una única instancia: El patrón Singleton asegura que solo haya una instancia de una clase determinada en todo el programa. Esto puede ser útil cuando se necesita un objeto único para coordinar acciones en diferentes partes del código.
Acceso global: Al utilizar el patrón Singleton, la instancia única se vuelve accesible globalmente desde cualquier parte del programa. Esto simplifica el acceso a la funcionalidad proporcionada por la clase, ya que no es necesario pasar la instancia entre diferentes componentes o clases.
Mantiene el estado: Si la clase Singleton tiene estado, este estado se mantiene a lo largo de todo el ciclo de vida de la aplicación. Esto puede ser útil cuando se necesita mantener información o configuraciones específicas en un solo lugar y compartirlas en diferentes partes del programa.
Promueve el acoplamiento débil: Al utilizar el patrón Singleton, los componentes o clases que dependen de la instancia no necesitan conocer los detalles de cómo se crea o se mantiene esa instancia. Solo necesitan solicitar la instancia al Singleton, lo que promueve un acoplamiento débil y facilita la modificación o sustitución de la implementación del Singleton en el futuro.
. Sin embargo, es importante tener en cuenta que el patrón Singleton también puede tener algunas desventajas. Por ejemplo, puede dificultar las pruebas unitarias, ya que la dependencia de la instancia única puede ser difícil de simular o reemplazar en las pruebas. Además, el uso excesivo del patrón Singleton puede ocultar dependencias y dificultar la comprensión del flujo de datos y la arquitectura general del programa. . Por lo tanto, es recomendable utilizar el patrón Singleton con moderación y evaluar cuidadosamente si es la mejor solución para el problema específico que se está abordando.
Andre Huaman Yovera
EstudianteSi deseas utilizar el patrón Singleton en tu código, puedes modificarlo de la siguiente manera:
(async () => { const url1 = 'https://api.escuelajs.co/api/v1/products'; const productService = BaseHttpService.getInstance<Product>(url1); const rta = await productService.getAll(); console.log('products', rta.length); const url2 = 'https://api.escuelajs.co/api/v1/categories'; const categoryService = BaseHttpService.getInstance<Category>(url2); const rta1 = await categoryService.findOne('2'); console.log('category', rta1); })();
En este caso, en lugar de crear nuevas instancias de BaseHttpService utilizando el operador new, utilizamos el método estático getInstance para obtener la instancia única de la clase. Esto asegura que siempre estemos utilizando la misma instancia de BaseHttpService en todo el código.
.
Ten en cuenta que en este ejemplo se está utilizando el método getInstance con diferentes URL y tipos de clase (Product y Category), lo cual está permitido debido a la implementación genérica de la clase BaseHttpService. Cada llamada a getInstance con una URL diferente creará una nueva instancia de BaseHttpService asociada a esa URL. Sin embargo, si se realiza una llamada adicional a getInstance con la misma URL, se obtendrá la misma instancia previamente creada.
.
De esta manera, el patrón Singleton garantiza que siempre estemos trabajando con una única instancia de BaseHttpService para cada URL, lo cual puede ser beneficioso para compartir el estado y la funcionalidad de la clase en diferentes partes del código.
Frank Yupanqui
EstudiantePersonalizando la clase en execution time.
Brahyan Antonio Martinez Madera
EstudianteTypescript the best💙
Raycris Maldonado
EstudianteTuve que mirar la clases dos veces para poder entender un poco más acerda de la clases generics pero aquí está el resumen que pude sacar
++RESUMEN:++ Este es un servivio generico que podemos utilizar solamente pasando el tipo de dato que queremos utulizar o hacer request, eso nos ahorraria hacer un servicio para productos, categorias, usuarios etc...
Andrés Felipe Eslava Zuluaga
EstudianteMi aporte:
import axios from 'axios'; import { Category } from '../models/category.model'; import { Product } from '../models/product.model'; export class BaseHttpService<TypeClass> { // data: TypeClass[] = []; constructor (private url: string) {} async getAll(): Promise<TypeClass[]> { const { data } = await axios.get<TypeClass[]>(this.url); return data; } } (async () => { const URL_PRODUCTS = 'https://api.escuelajs.co/api/v1/products' const URL_CATEGORIES = 'https://api.escuelajs.co/api/v1/categories' const productService = new BaseHttpService<Product>(URL_PRODUCTS); const categoryService = new BaseHttpService<Category>(URL_CATEGORIES); const products = await productService.getAll() const categories = await categoryService.getAll() console.log('products: >>>> ', products.length); console.log('categories: >>>> ', categories.length); })()
Miguel Angel Reyes Moreno
EstudianteGenerics en clases
import axios from "axios"; import { Category } from "./models/category.model"; import { Product } from "./models/product.model"; export class BaseHttpService<TypeClass> { constructor( private url: string, ) { } async getAll() { const { data } = await axios.get<TypeClass[]>(this.url) return data; } } (async()=> { const url1 = 'https://api.escuelajs.co/api/v1/products' const productService = new BaseHttpService<Product>(url1) const rta = await productService.getAll() console.log('products: ', rta.length) const url2 = 'https://api.escuelajs.co/api/v1/categories' const categoryService = new BaseHttpService<Category>(url2) const rta2 = await categoryService.getAll() console.log('categories: ', rta2.length) })()