Express + typescript 환경에서 로그인 부분을 구현하는 도중에 로그인을 성공했을 시 로그인한 정보중에 hash된 비밀번호와 admin 속성은 보여주지 않기 위해 구조 분해 할당을 하여 코드를 작성하였다.
login 코드
export const login = async (
req: express.Request,
res: express.Response,
next: NextFunction
) => {
try {
const user = await User.findOne({ username: req.body.username });
if (!user) return next(createError("404", "User not found!"));
const isPasswordCorret = await bcrypt.compare(
req.body.password,
user.password
);
if (isPasswordCorret)
return next(createError("400", "Wrong password or username"));
const { password, isAdmin, ...otherDetails } = user;
res.status(200).json({ ...otherDetails });
} catch (err) {
next(err);
}
};
실제 로그인했을 경우 응답을 받은 결과인데 보는 것처럼 내가 원하는 정보들은 _doc라는 이름에 객체 안에 담겨있었다. 그렇기 때문에 const { password, isAdmin, ...otherDetails } = user 코드 부분을 { password, isAdmin, ...otherDetails } = user._doc로 작성하였다. 그런데 Property '_doc' does not exist on type 'Document<unknown, {}, IUser> & IUser & { _id: ObjectId; }'.ts(2339) 에러가 발생하였다. 당연하게도 내가 작성한 인터페이스에는 아래 코드처럼 작성되었기 때문에 _doc라는 property가 존재하지 않는다.

interface code
interface IUser {
username: string;
email: string;
password: string;
isAdmin: boolean;
}
interface code에 _doc 속성을 추가를 할까 했지만 user를 생성할 때 _doc 이름의 속성은 사용되지 않으므로 맞지 않는 방법 같았다. google을 검색한 결과 나와 정말 똑같은 문제를 마주한 질문과 답이 있었다.
_doc라는 속성을 가지고 제네릭 타입을 사용하는 DocumentResult 인터페이스를 작성하고 기존에 존재하던 IUser 인터페이스로 상속을 하여 타입을 IUser를 타입으로 사용하는 것이다.
기존에 사용하려던 const { password, isAdmin, ...otherDetails } = user._doc; 코드가 에러없이 작동하고 원하는 결과를 얻을 수 있었다.
interface DocumentResult<T> {
_doc: T;
}
interface IUser extends DocumentResult<IUser> {
username: string;
email: string;
password: string;
isAdmin: boolean;
}
