firebase-js-sdk
firebase-js-sdk copied to clipboard
[SDK v9] Firestore `updateDoc` generates TypeScript Error when using Mapped Types
Describe your environment
- Operating System version: Windows 11
- Browser version: not relavent
- Firebase SDK version: 9.6 (with TypeScript 4.5)
- Firebase Product: Firestore database
Describe the problem
- Firestore
updateDoc
generates TypeScript error when using Mapped Types. - The problem occurs only after updating to v9 modular SDK.
Steps to reproduce:
- Create a TS interface with a property of mapped type.
- Call
updateDoc
and pass an object of the interface created as the update data. - The following TypeScript error is generated.
Type 'Preference' is not assignable to type 'AddPrefixToKeys<"ratings", { [x: string]: number | FieldValue; }>'.
Index signature for type '`ratings.${string}`' is missing in type 'Preference'.ts(2345)
Relevant Code:
export interface Preference {
defaultRating: number;
ratings: { [name: string]: number };
}
const preference: Preference = { /* ... */ };
updateDoc( /* ... */ , preference);
@HazyFish Can you provide a repro of what you're passing into the preference
variable? I was able to compile the following code fine on my machine:
interface Preference {
defaultRating: number;
ratings: { [name: string]: number };
}
const preference: Preference = {
defaultRating: 5,
ratings: {
foo: 3
}
};
await updateDoc(doc(db,'foo/bar'), preference);
Looks like the error occurs only when the property containing the mapped type is one or more level(s) deeper than the document data model.
export interface DocDataModel {
preferences: Preferences;
}
interface Preferences {
ratings: { [name: string]: number };
}
collectionRef: CollectionReference<DocDataModel> = /* ... */ // whether the collection is typed or not, error will always be produced, but with different error messages.
update(id: string, update: DocDataModel): Promise<void> {
return updateDoc(doc(this.collectionRef, id), update); // error produced here
}
Error message when collectionRef
is not typed:
Argument of type 'DocDataModel' is not assignable to parameter of type '{ [x: string]: any; } & AddPrefixToKeys<string, any>'.
Type 'DocDataModel' is not assignable to type 'AddPrefixToKeys<string, any>'.
Index signature for type '`${string}.${string}`' is missing in type 'DocDataModel'.ts(2345)
Error message when collectionRef
is typed:
Argument of type 'DocDataModel' is not assignable to parameter of type '{ preferences?: FieldValue | ({ ratings?: FieldValue | { [x: string]: number | FieldValue | undefined; } | undefined; } & AddPrefixToKeys<"ratings", { [x: string]: number | ... 1 more ... | undefined; }>) | undefined; }'.
Types of property 'preferences' are incompatible.
Type 'Preferences' is not assignable to type 'FieldValue | ({ ratings?: FieldValue | { [x: string]: number | FieldValue | undefined; } | undefined; } & AddPrefixToKeys<"ratings", { [x: string]: number | FieldValue | undefined; }>) | undefined'.
Type 'Preferences' is not assignable to type '{ ratings?: FieldValue | { [x: string]: number | FieldValue | undefined; } | undefined; } & AddPrefixToKeys<"ratings", { [x: string]: number | FieldValue | undefined; }>'.
Type 'Preferences' is not assignable to type 'AddPrefixToKeys<"ratings", { [x: string]: number | FieldValue | undefined; }>'.
Index signature for type '`ratings.${string}`' is missing in type 'Preferences'.ts(2345)
@HazyFish I was able to reproduce the issue with TS v4.5. The issue isn't present on v4.4.x.
I'll leave this issue open, but we probably won't prioritize this immediately since our SDK is still on TS v4.2.2.
I am getting the same error message.
Firebase JS SDK version 9.6.6, with TypeScript version 4.5.4.
Mine is showing when typing any object and using that for the update function.
Example:
export interface User {
name: string;
}
const user: User = {
name: 'Mary'
};
updateDoc( /* ... */ , user);
The same error also shows during batch updates (i.e. batch.update(/* ... */, user)
;
Hello. Any update regarding this issue? Is a more recent version of typescript planned on being supported?
Also running into this with the following interface used to describe the type of object I'm trying to update:
export interface Task {
id?: string;
title: string;
description: string;
}
I am still having the same issue with Firebase 9.13 and Typescript 4.7.4 (supported by the latest firebase package). @thebrianchen are you able to replicate the issue as well with the new version?
I faced the same issue before, you have to pass into the updateDoc same object in new object by spread operator.
export interface Preference {
defaultRating: number;
ratings: { [name: string]: number };
}
const preference: Preference = { /* ... */ };
updateDoc( /* ... */ , {...preference});
I faced the same issue before, you have to pass into the updateDoc same object in new object by spread operator.
export interface Preference { defaultRating: number; ratings: { [name: string]: number }; } const preference: Preference = { /* ... */ }; updateDoc( /* ... */ , {...preference});
It worked. Thanks for the suggestion.
Facing the same with
import * as admin from 'firebase-admin';
const db = admin.firestore();
db.collection(DB_COLLECTION_NAMES.UserAttribution)
.doc(uid)
.update(userAttribution)
FYI, the firebase-admin
SDK is a separate repo, here: https://github.com/firebase/firebase-admin-node
Maybe this simple example helps somebody:
interface ICompany {
id?: string
dateAdded: Date
dateEdited: Date
description: string
logo?: string
managers?: ICompanyManager
name: string
website?: string
}
const companyData = {
dateEdited: new Date(),
description: data.description,
name: data.name,
website: data.website,
} as ICompany
await updateDoc(companyRef, { ...companyData })
This works ✅ and you won't get the warning.
This is fixed in the v10.0.0 release: https://firebase.google.com/support/release-notes/js#version_1000_-_july_6_2023