Tipando respuestas HTTP
Clase 16 de 25 • Curso de TypeScript: Programación Orientada a Objetos y Asincronismo
Contenido del curso
Clase 16 de 25 • Curso de TypeScript: Programación Orientada a Objetos y Asincronismo
Contenido del curso
luis onate
Fabricio Orrala
Axel Enrique Galeed Gutierrez
Juan Camilo Cruz Franco
Enrique Manuel Sánchez Castañeda
Rodrigo Isaac Carrera Estrada
Ivan Sangueza Alarcon
Christian Camilo Guzman Zapata
Steve Anthony Luzquiños Agama
Diego Andres Gonzalez Marrugo
Bryan Key
Cesar More Sanchez
yeferson soto
Jean Paul Yepes
Fredy CM
David Higuera
Carlos Alberto De Avila Suro
Carlos S. Aldazosa
Andrés Felipe Eslava Zuluaga
Carlos S. Aldazosa
Alfonso Neil Jiménez Casallas
Christian Velázquez
Ronaldo Delgado
Angel Hernandez
Paola Alapizco
Diego Raciel Ortega Hernandez
Una forma alternativa de realizar peticiones Https con ASYNC o THEN, ya que a muchos como yo no les gusta depender de una libreria externa.
ASYNC
const getProducts = async (url: string): Promise<Welcome[]> => { let data = await fetch(url); let res: Promise<Welcome[]> = data.json(); console.log(res); return res; }; getProducts("https://api.escuelajs.co/api/v1/products");
THEN
const getProducts2 = (): Promise<Welcome[]> => { return fetch("https://api.escuelajs.co/api/v1/products") .then((res) => res.json()) .then((json: Welcome[]) => { console.log(json); return json; }); }; getProducts2()
Gracias por el aporte!
Les comparto mis apuntes. :D
Quicktype
Esta página transforma nuestro archivo JSON en el tipado que le corresponde al mismo para poder tipar nuestras repuestas HTTP.
Tipado en funciones asíncronas con peticiones HTTP
Es importante poder tipar tanto nuestras funciones, ya sea inferidamente o explícitamente, como las variables que manejamos internamente dentro de ella.
Tipado en Axios
Aserción angle bracket
Axios nos permite tipar las peticiones que hacemos de la siguiente manera.
const { data } = axios.get<dataType>(URL);
Aserción AS
También podemos realizar el tipado por medio de aserción de tipos con as, pero lo ideal es hacerlo con el primer método.
async function getProductsAsync () { const rta = await axios.get(URL); const data = rta.data as Product[]; return data; }
Código de la clase
import axios from 'axios'; import { Product } from './models/product.model'; const URL = 'https://api.escuelajs.co/api/v1/products'; // let anyVar: any = 12; // let boolVar: boolean = anyVar; (async () => { // async function getProductsAsync (): Promise<Product[]> { // const { data } = await axios.get(URL); // return data; // } // async function getProductsAsync () { // const { data } = await axios.get<Product[]>(URL); // return data; // } async function getProductsAsync () { const rta = await axios.get(URL); const data = rta.data as Product[]; return data; } const products = await getProductsAsync(); console.log(products.map(({id, title}) => `${id} - ${title}`)); })()
no se dice "asainc" ==> se dice "eisinc"
el que apenas sabe el verbo to be xD
En el 2026 fetch ya se soporta de forma nativa en Node JS.
La forma de tipar la respuesta de fetch podria ser asi:
async function getProductsAsync(): Promise<Product[]> { const response = await fetch("https://api.escuelajs.co/api/v1/products").then(res => res.json()) as Product[]; return response; }
Les dejo la extensión para VSCode
https://marketplace.visualstudio.com/items?itemName=quicktype.quicktype
Gracias justo la estaba buscando ^^
Este tipo de tipado se llama: Genérico, estaría buenísimo si Platzi hiciera un curso de tipos Genéricos avanzados, ya que soy muy útiles.
Lo que me causa curiosidad sobre Typescript es como automaticamente puede mapear los datos hacia un objeto, a diferencia de otros lenguajes como Java o PHP se necesita un mapeador de datos para lograr esta funcionalidad,
Creo ojo CREO, que es porque typescript como tal, solo por detras le coloca el tipado a javascript, osea transforma a JS y JS solo se encarga de hacer validaciones directas en el codigo, no es una magia digamoslo asi.
Chicos, esto de poder tipar las respuestas HTTP es muy importante y te ahorrarás muchos dolores de cabeza cuando ya estés trabajando. Cuando trabajaba con JS puro tenía demasiados errores por undefined o null ya que muchos de los campos que me envían las API aún no están definidas y terminaba rompiendo mi app cada vez que avanzaba.
agrego codigo que puede probar con la version de nodejs del 2023 sin librerias
//import fetch from "node-fetch"; test con node const API_URL = 'https://api.escuelajs.co/api/v1/products'; import {Product} from './product.model'; const request = new Request(API_URL);//aqui personalizo las peticiones //tipado hacia afuera const getProductsFetch = async ():Promise<Product[]> => { try { const promise = await fetch(request); if(!promise.ok){ throw new Error(`Error ${promise.status}: Failed Connection to Server`); } const response = await promise.json(); return response; } catch (error) { console.error(error); return []; } } (async ()=>{ const products = await getProductsFetch(); console.log(products.map(({id, title})=>`${id} - ${title}`)); })(); //tipado hacia adentro const getProductsFetchV2 = async () => { try { const promise = await fetch(request); if(!promise.ok){ throw new Error(`Error ${promise.status}: Failed Connection to Server`); } const response:Product[] = await promise.json(); console.log(response.map(item=>`${item.price}`)); return response; } catch (error) { console.error(error); return []; } } getProductsFetchV2(); //cuando el metodo no soporta tipado const getProductsFetchV3 = async () => { try { const promise = await fetch(request); if(!promise.ok){ throw new Error(`Error ${promise.status}: Failed Connection to Server`); } const response = await promise.json() as Product[]; console.log(response.map(item=>`${item.creationAt}`)); return response; } catch (error) { console.error(error); return []; } } getProductsFetchV3();
Hay otra manera para tipar el retorno como un arreglo de Productos, se puede usar el destructuring para tipar data:
async function getProducts() { const { data } : { data: Product[]} = await axios.get<Product[]>( 'https://api.escuelajs.co/api/v1/products' ); return data; }
Excelente en verdad si que estoy aprendiendo mucho!!
Recomiendo ampliamente la extension de Quick Type para VSCode. Es muy útil :)
Veamos cómo podemos hacer el tipado de esas respuestas HTTP . creamos una nueva sub carpeta dentro de src y la llamamos app dentro creamos un archivo llamado reciclamos en el el codigo anterior y lo modificamos para que quede así:
import axios from "axios"; ( async ()=>{ async function getProducts(){ const rta = await axios.get("https://api.escuelajs.co/api/v1/products") return rta.data } const productsAsync = await getProducts() console.log(productsAsync) } )()
Si paso el apuntador por la declaracion de getProducts vere que indica el tipo any, algo asi como lo siguiente
promise<any>
Lo cual significa que la constante productsAsync será un arreglo con tipos any, esto ¿que significa?, veamos, imaginate que tienes declarada una variable de tipó any y le asignamos cualquier cosa, digamos un numero
let anyVar: any = 12
y luego declaramos otra variable de tipo bool pero le asignamos la variable anterior, es decir anyVar
let boolVar:boolean = anyVar
aunque boolVar es de tipo boolean, ts acepta que se le asigne anyVar que contiene un número, no manda ningun error, la razón es por que any indica que podría ser cualquier cosa, incluso un valor boolean, es como quitarle a ts el poder de validar los tipos de los valores asignados a una variable de un tipo determinado, eso esta mal. Una forma de evitar estos problemas es que en lugar de usar una variable de tipo any, usar una de tipo unknow que al menos permite hacer una validación de tipos, sin embargo lo mejor es definir el tipado correcto de nuestros productos para ello nos vamos a nuestra subcarpeta models y crearemos (por asi decirlo) un archivo llamado en el cual definimos las interfaces de nuestros productos que quedaria de la siguiente forma:
export interface Product { id: number; title: string; price: number; description: string; category: Category; images: string[]; creationAt: Date; updatedAt: Date; } export interface Category { id: number; name: string; slug: string; image: string; creationAt: Date; updatedAt: Date; }
Nota: para generar el codigo anterior hemos usado la pagina de , donde indicamos que solamente usaremos ts, pegamos un objeto de ejemplo y nos genera el codigo para la interfaz de manera automática.
Como se ve generó también la interfaz Category ya que nuestro objeto contiene un subobjeto que también debe ser tipado con otra interfaz por lo tanto separamos ese codigo de Category, creamos otro archivo llamado y ahi ponemos el codigo de la categoria para seguir el principio de separación de problemas y poder maximizar la reutilización del codigo y otros beneficios. ahora este archivo category,models.s contiene la interface de categorias, entonces lo importamos desde
import {Category} from "./category.model";
Ahora estas interfases nos serviran para tipar la salida de la promesa en la función getProducts, primero debemos importar la interface
import {Product} from "./models/products.model"
Y después indicar el tipo con <Product[]> (esta es la notacion de los tipos genéricos)
async function getProducts(): Promise<Product[]>{ const rta = await axios.get("https://api.escuelajs.co/api/v1/products") return rta.data }
Aquí estás diciendo: “Axios, espero que la respuesta tenga como data un arreglo de productos.”
También Axios soporta este tipo de tipado prodirmos cambiar la funcion de la siguiente manera:
( async ()=>{ async function getProducts(){ const rta = await axios.get <Product[]>("https://api.escuelajs.co/api/v1/products") return rta.data } console.log("-".repeat(30)) const productsAsync = await getProducts() // console.log(productsAsync) productsAsync.map(item=>{ console.log(id -> ${item.id} Description-> ${item.title}) }) } )()
Con lo cual cambió de lugar el tipado genético, se pasa a la asignación rta que hacemos a la variable.
En caso de que estemos usando una libreria que no soporte el tipado, podriamos forzarlo de la siguiente manera
const data = rta.data as Product[]
Entonces dejarlo de esta manera sería redundante?
async function getProducts(): Promise<Product[]> { const { data } = await axios.get<Product[]>('https://api.escuelajs.co/api/v1/products'); return data; }
No es que sea redundante. VS Code ya entiende el valor inferido que tiene la respuesta de get.
Lo que significa es que al momento de crear la promesa y solo tener una devolución de su respuesta, TS y el editor entienden qué se devuelve de la función.
Incluso, en la forma que lo estás expresando, es un poco más verbose, que lo hace muucho más explícito.
Gracias por la aclaración!
se te fue un } de más, Nicobytes
Platzi Store: https://fakeapi.platzi.com/
excelente como typescript nos ayuda con nuestra programación
interesante ahora con chat-gpt puedo tener el mismo resultado (o muy similar) de lo que puede hacer quicktype. Aqui mi ejemplo:
interface Category { id: number; name: string; image: string; creationAt: string; updatedAt: string; } interface Product { id: number; title: string; price: number; description: string; images: string[]; creationAt: string; updatedAt: string; category: Category; } type Products = Product[];
Herramienta para convertir un objeto en una interfaz.
:0 enamorado de TS