Solucionado: El Error "Type Props does not satisfy PageProps" en Next.js 15

Publicado por Miguel Trejo el 2025-06-20

Si estás desarrollando con las últimas versiones de Next.js, es posible que te hayas topado con uno de los errores más confusos y frustrantes del ecosistema reciente. Tu aplicación funciona a la perfección en local (npm run dev), pero cuando intentas desplegarla en Vercel, el build falla con un mensaje que no parece tener sentido: Type error: Type 'Props' does not satisfy the constraint 'PageProps'. Types of property 'params' are incompatible. Type '{ id: string; }' is missing the following properties from type 'Promise': then, catch, finally...

Después de una intensa sesión de depuración, he identificado la causa raíz y la solución definitiva. Y no, el problema no está (directamente) en tu tipado.

El Diagnóstico: Un "Breaking Change" en Next.js 15

La clave está en la documentación de las últimas versiones de Next.js. Para habilitar futuras optimizaciones de rendimiento como el "Partial Prerendering", Next.js ha introducido un cambio radical (breaking change) en la forma en que los Componentes de Servidor (async components) acceden a los datos de la petición.

En Next.js 15, el objeto params que recibe una página dinámica ya no es un objeto simple, ahora es una Promise que debe ser resuelta.

El error ...is missing the following properties from type 'Promise<any>' es la forma en que TypeScript nos grita que estamos tratando una promesa como si fuera un objeto normal.

La Solución: await los ParámetrosSSS

La solución es sorprendentemente simple una vez que se entiende el problema. Debemos "esperar" a que la promesa de los parámetros se resuelva antes de intentar usarlos.

Veamos el código.

El Código Incorrecto (Estilo Next.js 14)

Probablemente tenías algo así en tu página app/blog/[slug]/page.tsx, que funcionaba en versiones anteriores:

// ¡Este código falla en Next.js 15!
type Props = {
  params: { id: string };
};

export default async function Post({ params }: Props) {
  // ERROR: Aquí, 'params' es una Promise, no un objeto.
  const postData = await getPostData(params.id); 
  // ...
}

El Código Corregido (Sintaxis para Next.js 15) Para solucionarlo, simplemente necesitamos añadir await al acceder a los params que vienen en las props.

// El tipo ahora refleja que los params son una promesa
type Props = {
  params: Promise<{ id: string }>;
};

// Esta firma también puede funcionar, siendo más directa:
// export default async function Post(props: { params: Promise<{ id: string }> }) {

export default async function Post({ params: paramsPromise }: Props) {
  // LA LÍNEA CLAVE DE LA SOLUCIÓN:
  // "Abrimos" la promesa para obtener el objeto de parámetros.
  const params = await paramsPromise;

  // Ahora sí podemos usar params.id de forma segura.
  const postData = await getPostData(params.id);

  // ... el resto de tu componente
}

Es importante notar que esta lógica se aplica tanto al componente de la página como a la función generateMetadata, ya que ambas reciben los mismos params.

Conclusión

Este cambio, aunque pequeño en código, representa un cambio de paradigma fundamental en cómo Next.js maneja los datos de la ruta. Comprender que params y searchParams ahora son asíncronos en los Componentes de Servidor es crucial para evitar horas de depuración frustrante. La lección es clara: mantenerse al día con los "breaking changes" de los frameworks que amamos es tan importante como escribir buen código. Espero que esta guía te haya ahorrado el dolor de cabeza que yo sufrí. Si buscas un desarrollador que no solo construye webs, sino que se obsesiona con entender cómo funcionan por dentro para hacerlas más robustas y eficientes contactame.