Next.js App Router를 쓰면서,
npm run build 수행 시 API Router의 context 파라미터 관련해서 타입 에러가 발생하는 현상을 경험했다.
특히, 아래와 같은 에러 메시지와 함께 빌드가 막혔다.
Type error: Type '{ __tag__: "POST"; __param_position__: "second"; __param_type__: { params: { id: string; }; }; }' does not satisfy the constraint 'ParamCheck<RouteContext>'. The types of '__param_type__.params' are incompatible between these types. Type '{ id: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]
문제 상황
기존에 Next.js 공식 문서 예시와 같이 Route Handler를 작성했지만,
TypeScript가 context 파라미터의 타입을 Promise로 요구하면서 에러가 발생했다.
기존 코드
export async function POST(
request: NextRequest,
context: { params: { id: string } }
) {
try {
const params = (await context).params;
const id = params.id;
// ...
} catch (error) {
// ...
}
}
npm run build가 실패해서 배포까지 불가능했다.
해결 방법
타입 에러 메시지를 유심히 살펴보니,
params가 Promise 타입을 요구한다는 것을 알 수 있었다.
즉, 아래처럼 context의 구조분해 시
params를 Promise로 선언하고, 사용시 await을 붙이면
정상적으로 빌드가 된다.
변경 후 코드
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const id = (await params).id;
// ...
} catch (error) {
// ...
}
}
- { params }: { params: Promise<{ id: string }> }
→ params가 Promise 타입임을 명시 - const id = (await params).id;
→ 실제 사용 시 await으로 값을 받아옴
정리
- Next.js 15 + TypeScript 환경에서는
route handler의 context 파라미터가 params: Promise<{ id: string }> 형태로 추론될 수 있다. - 공식문서 예시처럼
{ params: { id: string } }으로만 선언하면
타입 에러가 발생할 수 있다. - 이럴 때는
params에 Promise 타입을 명시하고, 실제로 await해서 사용하면 빌드가 정상적으로 완료된다.
결론
Next.js App Router에서 타입 시스템이 바뀌고 있는 중이라, 버전마다 다소 동작이 달라질 수 있다고 한다.
해당 문제는 주로 15버전 이상부터 발생하는 것 같으니, 버전을 다운그레이드 해보는 것도 좋은 방법일 것 같다.