interface FindUserEmailProps {
readonly email: string
}
interface FindUserIdProps {
readonly id: string
}
type FindUserProps = FindUserEmailProps | FindUserIdProps
export const findUserByEmail = async ({ email }: FindUserProps): Promise<IUser> => {
const user = await User.findOne({ email })
if (!user) {
throw new Error('User not found')
}
return user
}
At email property I got TS2339: Property 'email' does not exist on type 'FindUserProps' Why is that?
CodePudding user response:
That's because FindUserProps
can be one of FindUserEmailProps
or FindUserIdProps
but it's not both (that would be FindUserEmailProps
& FindUserIdProps
). That means that TypeScript doesn't know which one it is until you assert it.
Your function has to take a FindUserProps
and needs to add your own type guard to let TypeScript know whether it's a FindUserEmailProps
or FindUserIdProps
before you can extract an email
property.
// Custom type guard that lets TypeScript know whether your
// object is a FindUserEmailProps
function isFindUserEmailProps(obj: FindUserProps): obj is FindUserEmailProps {
return "email" in obj;
}
export const findUserByEmail = async (userProps: FindUserProps): Promise<IUser> => {
// You have to make sure it's a FindUserEmailProps
if (!isFindUserEmailProps(userProps)) {
// Since you are just throwing an error, you may as well
// change your function to only accept a FindUserEmailProps
throw new Error("Invalid userProps to find by email");
}
const {email} = userProps;
const user = await User.findOne({ email })
if (!user) {
throw new Error('User not found')
}
return user
}