I am using this useFirestore() wrapper provided by VueUse.org
And I'm trying to type the user
ref it returns with User
, like this:
import { User } from 'src/types';
const userId = useUserStore().user.id;
const userDocRef = doc(db, 'users', userId);
const user = useFirestore<User>(userDocRef); // <-- Error shows here
And this is what my User
interface looks like:
export interface User {
id: string;
userType?: UserType;
createdAt?: Timestamp;
email?: string;
displayName?: string;
firstName?: string;
lastName?: string;
initials?: string;
passwordUpdatedAt?: Timestamp;
photoUrl?: string;
phoneE164Format?: string;
phoneNationalFormat?: string;
stripeId?: string;
stripeLink?: string;
googleTokens?: {
access_token: string;
expiry_date: number;
id_token: string;
refresh_token: string;
token_type: string;
};
}
This works. The user
variable now has intellisense with User
properties.
But it also produces this error on userDocRef
:
No overload matches this call. Overload 1 of 4, '(maybeDocRef: MaybeRef<DocumentReference>, initialValue?: User | undefined, options?: UseFirestoreOptions | undefined): Ref<...>', gave the following error. Overload 2 of 4, '(maybeDocRef: MaybeRef<Query>, initialValue?: User[] | undefined, options?: UseFirestoreOptions | undefined): Ref<...>', gave the following error.ts(2769)
At the bottom of the useFirestore() docs it has a section named "Type Declarations" which might help. But it is hard for me to fully understand.
I think I am doing the correct thing by passing User
as a generic. So I am not sure why I get this error.
Why am I seeing this error and how to fix it?
I figured it out.
My interface had a required id
property that was causing a conflict.
Here is the full final code:
const userId = useUserStore().user.id;
const userDocRef = doc(db, 'users', userId);
const user = useFirestore<User>(userDocRef);
export interface User {
id?: string; // <-- Updated here
userType?: UserType;
createdAt?: Timestamp;
email?: string;
displayName?: string;
firstName?: string;
lastName?: string;
initials?: string;
passwordUpdatedAt?: Timestamp;
photoUrl?: string;
phoneE164Format?: string;
phoneNationalFormat?: string;
stripeId?: string;
stripeLink?: string;
googleTokens?: {
access_token: string;
expiry_date: number;
id_token: string;
refresh_token: string;
token_type: string;
};
}
This answers the question and fixes my immediate problem, but I'm not sure why I need all interface properties to be optional. That seems quite restrictive.
If anyone knows why please comment below.