인프런 커뮤니티 질문&답변

xocoolree님의 프로필 이미지

작성한 질문수

탄탄한 백엔드 NestJS, 기초부터 심화까지

passport와 인증 전략 & Custom decorator

findCatByIdWithoutPassword 함수 리턴 타입 질문

작성

·

231

·

수정됨

1

  async findCatByIdWithoutPassword(id: string): Promise<Cat | null> {
    const cat = await this.catModel.findById(id).select('-password');
    return cat;
  }

위 함수에서 Pomise의 반환값이 Cat 또는 null인데 cat은 password가 없는 Cat이라서 Cat이라고 할 수 없는데 return을 cat으로 해도 에러가 안나는 이유를 알고 싶습니디.

답변 2

1

저도 그 문제를 고민해봐서 찾아본 결과를 공유하겠습니다.

우선 Cat의 경우, mongoose의 Document 클래스를 상속받았습니다.

그리고 findOne, findById, select 모두 Query<Document & Cat & { id }> 타입을 리턴합니다. (제네릭 타입은 무시했습니다)

&는 intersaction 기능을 수행하는 오퍼레이터로 Typescript 에서 서로 다른 필드는 합치고, 같은 필드는 더 작은 범위로 만들어줍니다. 자세한 내용은 공식문서를 참조하시거나 검색해보시면 더 잘 나오지만, 핵심은 이렇습니다.

Cat은 Document를 상속받았고,

&로 연결시켜도 Cat 에서 더 이상 변하지는 않습니다.

무엇보다도 아래 실험을 해보니 Typescript에서 허용하는 것이 있습니다:

class BaseClass {
  prop1: string;
}

class ClassA extends BaseClass {
  prop2: string | number;
}

type Combined = ClassA & BaseClass;

const combinedObject: BaseClass = {
  prop1: "1",
  prop2: 42,
} as ClassA; // Combined also ok

상속받아서 확장한 ClassA나 확장된 Combined 타입 모두 상속해준 Base클래스 타입으로 받는 것은 가능하고, 물론 동일한 타입끼리 선언하는 것도 가능합니다.

 

따라서, 우리가 작성했던 findOne이나 select를 통해 리턴된 값을 Promise<Cat>로 받는 것도 가능하고 Promise<Document>도 허용가능한 타입이 됩니다.

여기까지 제가 알아본 내용입니다.

도움이 되셨길 바랍니다.

0

안녕하세요, 인프런 AI 인턴이에요.

제시해주신 코드를 보면, findCatByIdWithoutPassword 함수는 catModel.findById(id) 메소드를 호출하여 해당 id에 해당하는 Cat 데이터를 가져오고 있습니다. 그리고 select(‘-password’)를 통해 가져온 Cat 데이터에서 password 필드를 제외한 데이터를 선택하고 있습니다.

이후에는 반환된 cat 데이터를 그대로 return하고 있습니다. 여기서 cat 데이터는 catModel.findById(id) 메소드의 반환 값이기 때문에 타입을 Cat으로 지정해줄 수 있습니다.

만약에 catModel.findById(id) 메소드의 반환 값이 null이거나 비어있는 경우, 해당 조건에 맞게 null을 반환하게 됩니다. 이렇게 된다면 Promise의 반환값은 Cat 또는 null이 될 수 있게 되는 것이죠.

그래서 위의 코드에서 cat으로 반환하더라도 에러가 발생하지 않는 이유는, cat이라는 변수에는 선택된 필드를 제외한 Cat 데이터 또는 null 값이 할당되기 때문입니다.

따라서 cat이라는 변수의 타입은 Cat 또는 null이 가능하게 되며, 이를 아래와 같이 Promise로 지정할 수 있게 되는 것이죠.

이와 관련해서 추가로 궁금한 점이 있다면 댓글로 알려주세요. 감사합니다.

참고로 위의 코드와 같은 내용을 구현할 때, 다른 개발자들이 코드를 이해하기 쉽도록 명시적으로 타입을 지정하는 것이 좋습니다. return 타입을 정확히 명시하는 것이 코드의 가독성을 높일 수 있습니다.