typescript - Firebase + Typescript - ID 属性和 withConverter 问题(创建没有 ID 属性的新文档)

标签 typescript firebase google-cloud-firestore typescript-typings mobx-state-tree

让我尝试解释一下情况:

  1. 要在 firestore 中创建新文档,我使用 collection 中的 add 方法
  2. 为了保持类型安全,使用 typescript,我使用 withConverter
  3. 当我创建新文档时,我的对象没有 ID 属性
  4. 创建对象后,我就有了 ID 属性

bdw.. I'm using Mobx-state-tree

代码

让我一步步描述

mobx-state-tree定义的公司模型

const CompanyModel = types.model({
  id: types.identifier,
  name: types.string
});

我需要的类型

在我调用add方法后,CompanyReference是我从firestore获取的

type CompanyReference = firebase.firestore.DocumentReference<
  Instance<typeof CompanyModel>
>;

TCompanySnapshot 是我使用 add 方法发送到 firestore 的内容

type TCompanySnapshot = Omit<SnapshotIn<typeof CompanyModel>, "id">;

使用 withCOnverter 在 Firestore 之间进行转换

  • 将数据发送到 firestore,只需使用常规 TCompanySnapshot 对象
  • 从 firestore 接收一些对象(现在我有 ID 属性),转换为 CompanyModel
const createCompanyConverter: firebase.firestore.FirestoreDataConverter<Instance<
  typeof CompanyModel
>> = {
  toFirestore(modelObject: TCompanySnapshot): firebase.firestore.DocumentData {
    return modelObject;
  },
  fromFirestore(
    snapshot: firebase.firestore.QueryDocumentSnapshot<TCompanySnapshot>,
    options: firebase.firestore.SnapshotOptions
  ): Instance<typeof CompanyModel> {
    const data = snapshot.data(options);
    return CompanyModel.create({
      id: snapshot.id,
      ...data
    });
  }
};

问题

现在,当我尝试创建创建新公司的方法时,出现输入错误

function addCompany(
  // companyData: SnapshotIn<typeof CompanyModel>,
  companyData: TCompanySnapshot
): Promise<CompanyReference> {
  const added = firestore
    .collection("companies")
    // .withConverter<Instance<typeof CompanyModel>>(createCompanyConverter)
    .withConverter<TCompanySnapshot>(createCompanyConverter)
    .add(companyData);

  return added;   // <<<<<------ ERROR HERE
}

Property 'id' is missing in type

您可以在 code sandbox 上检查此错误

https://codesandbox.io/s/firebase-typescript-mobx-state-tree-n9s7o?file=/src/index.ts

最佳答案

您遇到的问题是由于您使用 withConverter() 引起的,这正在更改 CollectionReference 的类型这样它与您的 CompanyReference 不匹配.

参见 Firestore#collection() , CollectionReference#withConverter() CollectionReference#add() :

firestore
  .collection("companies")                                 // CollectionReference<DocumentData>
  .withConverter<TCompanySnapshot>(createCompanyConverter) // CollectionReference<TCompanySnapshot>  
  .add(companyData);                                       // Promise<DocumentReference<TCompanySnapshot>>

请注意DocumentReference<TCompanySnapshot> !== DocumentReference<Instance<typeof CompanyModel>> .

如果您对对象的转换方式感到满意,则可以使用以下行强制覆盖类型:

return added as Promise<CompanyReference>;

但是,您应该更正您的 FirestoreDataConverter实例。也不需要显式地重写所有内容,只需指定 firebase.firestore.FirestoreDataConverter<Instance<typeof CompanyModel>> 即可。因为结果的类型应该将适当的类型传播到其他对象。

const createCompanyConverter: firebase.firestore.FirestoreDataConverter<Instance<typeof CompanyModel>> = {
  toFirestore(modelObject) {
    const objToUpload = { ...modelObject } as firebase.firestore.DocumentData; // DocumentData is mutable
    delete objToUpload.id; // make sure to remove ID so it's not uploaded to the document
    return objToUpload;
  },
  fromFirestore(snapshot, options) {
    const data = snapshot.data(options); // "as Omit<Instance<typeof CompanyModel>, "id">" could be added here

    // spread data first, so an incorrectly stored id gets overridden
    return CompanyModel.create({
      ...data, 
      id: snapshot.id
    });
  }
};

关于typescript - Firebase + Typescript - ID 属性和 withConverter 问题(创建没有 ID 属性的新文档),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66241871/

相关文章:

类型转换时的 Typescript 默认属性

typescript - 防止 prettier-standard 删除 Typescript 接口(interface)中的分号

Firebase 云函数 -@google-cloud/storage 初始化

firebase - Firestore 定价;需要帮助理解文档中的短语

javascript - Firestore 和 Node.js : . set/.update => 将变量作为键传递

firebase - “task.future.then ”不断在我的Flutter代码中引发错误

node.js - 如何将 angular 4 添加到现有的 node.js 应用程序

typescript - 相当于 Typescript 的 Babel 插件?

ios - Tableview 搜索栏未正确返回 detailTextLabel(Xcode - Swift)

python - 通过环境变量初始化 Firebase Admin,而不存储 serviceAccount.json