스프링으로 개발할 때 보통 Response DTO를 간편하게 만들기 위해 파라미터로 entity를 받는 생성자를 하나 만들곤 했는데, NestJS로 개발할 때는 이 방식에 좀 문제가 있더라고.
Nest CLI로 NestJS 프로젝트를 만들면 기본적으로 tsconfig.json
에 strictPropertyInitialization
설정이 없어. 그래서 실수로 생성자에서 몇몇 필드 초기화를 빼먹어도 에러가 발생하지 않는단 말이지.
export class ProductResponseDto {
name: string;
price: number;
constuctor(product: Product) { // 아무런 에러도 발생하지 않음
this.name = product.name;
}
}
Q. "strictPropertyInitialization": true
설정을 넣어 주면 되는 거 아니야?
Response DTO는 돼. 근데 Request DTO들이 뻘겋게 물들 걸. 필드 초기화하는 생성자가 없다면서. 얘네는 애초에 생성자가 필요 없었는데 말이야.
뭐 다행히 불필요한 생성자를 만들어 주지 않고 좀 더 간단하게 해결하는 방법이 있긴 해.
Request DTO의 모오오든 필드에 !
(definite assignment assertion operator)를 붙여 주면 에러는 사라질 거야.
그리고 앞으로는 Request DTO 만들 때마다 모든 필드에 !
를 붙여야겠지.
거추장스럽고 성가시지 않겠어?
원하는 건 그저 필드 초기화를 빠뜨리면 에러를 발생시키는 건데.
TypeScript는 Type safety를 지키면서도 JavaScript의 유연함을 잃지 않았지.
함수 반환형과 plain object({}
)를 이용해서 해결해 보자.
export class ProductResponseDto {
name: string;
price: number;
static of(product: Product): ProductResponseDto {
return { // ERROR!
name: product.name,
}
}
}
생성자를 대신할 static 함수를 하나 만들었어.
이제 price
필드 초기화를 누락시키면 아래와 같은 에러가 발생해.
Property 'price' is missing in type '{ name: string; }' but required in type 'ProductResponseDto'.ts(2741)
어떤 필드가 누락되어서 에러가 발생했는지 아주 잘 알려주지.
이제 new
로 객체를 만드는 대신 static 메서드를 사용하자고.
new ProductResponseDto(product);
-> ProductResponseDto.of(product);