Kodokon kodokon.com

Tipar código del mundo real: DOM, fetch, JSON

Mantén tipos fiables en las fronteras de tu aplicación, donde el DOM, la red y el JSON escapan al compilador.

10 min · 3 preguntas

Abrir esta lección en Kodokon

El código del mundo real empieza donde terminan los tipos perfectos: el DOM, la red y el JSON devuelven datos que TypeScript no puede adivinar. Primera frontera: el DOM. querySelector devuelve Element | null, un tipo demasiado vago para leer value o llamar a focus().

TYPESCRIPT
const input = document.querySelector<HTMLInputElement>(
  "#email"
);

if (input) {
  input.value = "test@example.com";
  input.focus();
}
Un parámetro de tipo en querySelector y una guardia contra null

El parámetro de tipo es una promesa que le haces al compilador: es cosa tuya apuntar al selector correcto. Cuando el elemento proviene de un evento, prefiere una comprobación instanceof, que verifica de verdad el tipo en tiempo de ejecución.

TYPESCRIPT
const form = document.querySelector("form");

form?.addEventListener("submit", (event) => {
  event.preventDefault();
  if (event.target instanceof HTMLFormElement) {
    console.log(new FormData(event.target));
  }
});
instanceof comprueba y acota el tipo al mismo tiempo

Segunda frontera: la red. response.json() devuelve Promise<any>, es decir, una puerta abierta a cualquier cosa. El mínimo profesional: declarar el tipo esperado, comprobar response.ok y centralizar la llamada en una función tipada.

TYPESCRIPT
interface Post {
  id: number;
  title: string;
}

async function getPost(id: number): Promise<Post> {
  const url = `https://api.example.com/posts/${id}`;
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  return (await response.json()) as Post;
}
Una llamada fetch centralizada y tipada

Ese as Post sigue siendo una declaración de confianza: si la API cambia, nada te avisa en tiempo de ejecución. Para datos críticos, escribe una guardia de tipo que valide la forma real del JSON antes de usarlo.

TYPESCRIPT
function isPost(value: unknown): value is Post {
  if (typeof value !== "object" || value === null) {
    return false;
  }
  const obj = value as Record<string, unknown>;
  return (
    typeof obj.id === "number" &&
    typeof obj.title === "string"
  );
}
Una guardia de tipo que valida el JSON recibido (continuando el ejemplo)

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. ¿Cuál es el tipo de retorno de response.json() en una respuesta de fetch?
    • Promise<unknown>
    • Promise<any>
    • Promise<object>
    • any
  2. ¿Por qué preferir event.target instanceof HTMLFormElement en lugar de una aserción as HTMLFormElement?
    • Es más rápido en tiempo de ejecución
    • instanceof comprueba realmente el tipo en tiempo de ejecución, mientras que as se limita a silenciar al compilador
    • as está prohibido en modo estricto
  3. ¿Qué devuelve document.querySelector('#email') sin un parámetro de tipo?
    • HTMLInputElement
    • Element | null
    • HTMLElement
    • null