enunciados + leetcode
Enunciados como los de una entrevista real para resolver por tu cuenta, con el tiempo que te darían, y problemas de LeetCode recomendados para cada tecnología y seniority. Nada se corrige acá: resolvelo en tu editor, en voz alta, y marcá lo que ya practicaste.
Armá con Express y TypeScript una API mínima para una lista de tareas. Por ahora no hay base de datos: guardá todo en memoria en un array o un Map. Una tarea tiene la forma { id: string, title: string, done: boolean, createdAt: string }.
Necesitamos POST /tasks que recibe { "title": "Comprar café" } y responde 201 con la tarea creada, GET /tasks que devuelve todas, GET /tasks/:id y PATCH /tasks/:id que permite cambiar title o done. Si el body es inválido respondé 400 con { "error": "title es obligatorio" } o un mensaje equivalente.
# requisitos
title es obligatorio, string, sin espacios al principio ni al final y de 1 a 120 caracteres.PATCH solo acepta title y done; cualquier otro campo se ignora o se rechaza, pero decidilo y justificalo.id inexistente devuelve 404, no 500.201 al crear, 200 al leer y actualizar.# si te sobra tiempo, te van a preguntar
DELETE /tasks/:id y qué código devolverías?Map, reduce, sort) y tu atención a casos borde como montos y estados.30 minRecibís un array de órdenes con la forma { id: number, customerId: string, total: number, status: "paid" | "pending" | "cancelled" }. Escribí una función summarizeOrders(orders) que devuelva, por cada cliente, cuántas órdenes pagadas tiene y cuánto gastó en total.
Por ejemplo, para [{ id: 1, customerId: "a", total: 100, status: "paid" }, { id: 2, customerId: "a", total: 50, status: "cancelled" }, { id: 3, customerId: "b", total: 30, status: "paid" }] el resultado esperado es [{ customerId: "a", paidOrders: 1, totalSpent: 100 }, { customerId: "b", paidOrders: 1, totalSpent: 30 }], ordenado de mayor a menor totalSpent.
# requisitos
status igual a paid.Map u objeto), sin filtros anidados por cliente.# si te sobra tiempo, te van a preguntar
"10.10"?number puede dar resultados raros y cómo lo evitarías?async/await y el event loop lo suficiente como para escribir un helper asíncrono correcto y tipado.30 minTenemos que llamar a una API externa que a veces falla con errores transitorios. Escribí una función retry(fn, { retries, baseDelayMs }) que reciba una función que devuelve una promesa y la ejecute hasta que funcione o se agoten los reintentos.
Entre intento e intento esperá un tiempo que crece exponencialmente: baseDelayMs, después baseDelayMs * 2, después baseDelayMs * 4. Si todos los intentos fallan, la promesa devuelta tiene que rechazarse con el último error.
# requisitos
async/await y una función sleep(ms) basada en setTimeout y Promise.retries: 3 la función se ejecuta como máximo 4 veces (1 intento más 3 reintentos).fn resuelve, devolvé su valor sin esperar de más.retry<T>(fn: () => Promise<T>, ...): Promise<T>.# si te sobra tiempo, te van a preguntar
400?Map es un patrón que vas a repetir en cualquier agregación de datos.LEFT JOIN, que es lo primero que te preguntan de SQL en una entrevista backend.LEFT JOIN ... IS NULL o NOT EXISTS es una consulta de todos los días.