如何将数据模型类型与文档ID组合?

时间:2018-01-05 09:51:34

标签: firebase google-cloud-firestore

我正在使用Firestore和Typescript。

对于数据模型,我有类型定义。例如User可能是这样的:

interface User {
 name: string;
 age: number;
}

用户以唯一名称/ ID存储在users集合中的数据库中。

在查询集合时,在Firebase中,文档的ID在文档引用中可用,并且不附带数据。在前端的常见用例中,您希望使用其ID检索记录数组,因为您可能希望与它们进行交互并需要识别每个记录。

所以我做了一个类似于下面代码的查询,其中id被合并到结果数组中:

async function getUsers(): Promise<any[]> {
  const query = db.collection("users")

  const snapshot = await query.get();

  const results = snapshot.docs.map(doc => {
    return { ...doc.data(), id: doc.id };
  });
}

现在的问题是,我有一个用户类型,但由于它不包含id字段,因此无法在此处使用。

一个天真的解决方案可能是创建一个新类型:

interface UserWithId extends User {
  id: string
}

并编写如下函数:

async function getUsers(): Promise<UserWithId[]> {}

但这对我来说并不合适,因为你必须为许多类型做这件事。

我认为更好的解决方案是创建泛型类型:

type DatabaseRecord<T> = {
  id: string,
  data: T
}

因此,在返回的结果中保持数据和id分开:

const results = snapshot.docs.map(doc => {
  return { data: doc.data(), id: doc.id };
});

...并使用函数签名:

async function getUsers(): Promise<DatabaseRecord<User>[]> {}

我倾向于第一个解决方案,因为为每个案例创建新类型感觉很愚蠢。但我仍然不确定这是否是最佳方法。

这似乎是一种常见的情况,但我没有找到任何关于此的文档。我看到开发人员只是在模型数据中写id,基本上在其数据中复制了文档名称,但对我来说这似乎是一个很大的错误。

我可以想象如果你不使用Typescript(Flow),你只是不关心结果结构,只是将id与数据合并,但这是我真正喜欢使用类型的原因之一JS中的注释。它会迫使您更多地考虑您的数据,并最终编写更清晰的代码。

0 个答案:

没有答案