我使用的是www.example.com提供的useFirestore() Package 器VueUse.org
但是,当使用泛型键入useFirestore()
时,我不能使用具有可选属性的接口,因为TypeScript会引发以下错误:
没有与此调用匹配的重载
在下面的示例中,User
接口具有一个必需的name
属性,该属性会导致typescript引发错误。
interface User {
id?: string;
name: string; // <-- When this property is required the error will show, changing it to optional removes the error
}
const userQuery = doc(db, 'users', 'my-user-id');
const userData = useFirestore<User>(userQuery); // <-- The error shows here on "userQuery"
我找到了一个变通办法,但效果不太好。
您可以使用useFirestore(userQuery) as Ref<User>
来移 debugging 误并赋予它正确的类型。
但这样做并不是一个好的解决方案,因为我基本上是在告诉编译器“我知道得更清楚”,而不是编译器在说什么。因此,在不求助于这种解决方案的情况下,拥有正确的类型会更好。
interface User {
id?: string;
name: string;
}
const userQuery = doc(db, 'users', 'my-user-id');
const userData = useFirestore(userQuery) as Ref<User>; // <-- See changes made here
有没有更好的方法?
1条答案
按热度按时间xfb7svmp1#
想通了。
首先,错误的原因是
userQuery
被键入为DocumentReference<DocumentData>
,但useFirestore<User>(userQuery)
需要DocumentReference<User>
。由于这两个类型不匹配,因此显示了错误。要解决此问题,有两个选项:
选项1:
如原始问题所示,您可以 * 胁迫 *
useFirestore()
的传回值,如下所示:虽然这是可行的,但也有一些缺点:
1.它覆盖了编译器。我基本上是告诉它“我知道返回值是不同的,但我知道得更清楚,我知道它存在,所以用我的来代替”。这可能会导致不可预见的问题。
1.如果传递集合查询,则需要将其类型化为数组(
useFirestore(colQuery) as Ref<User[]>
);如果传递文档引用,则需要将其类型化为不包含数组(useFirestore(docRef) as Ref<User>
)。忘记这一点可能会导致其他错误。1.当使用
as
时,你会说“this thing exists and it has this type”。但是由于useFirestore
是异步的,有时数据并不存在,因为它仍在加载。因此它也应该有null
或undefined
的类型。因此,实际上最好使用useFirestore(userQuery) as Ref<User | null | undefined>
,您必须记住每次都要这样做,否则您可能会在尝试访问一些尚不存在的数据时出现问题。所有这些都是为了说明,我认为最好是正确地键入Firestore文档引用(或集合引用),然后让
useFirestore()
返回正确的类型,而不进行任何强制操作,因为强制操作可能会产生不可预见的问题。这就引出了第二个选择...
选项2:
在我看来这是上级的选择。
我在this medium article中发现了如何使用Firestore
withConverter()
将进出Firestore的数据转换为自定义对象(即TypeScript接口和类)。如果您更喜欢直接使用代码,那么this GIST可以满足您的所有需求。
但是这个解决方案是针对Firebase JavaScript Version 8 SDK的,我使用的是Firebase Modular JavaScript Version 9 SDK,它需要一些调整,如我的other question here所示。
简而言之,-
withConverter
可以用在Firestoredoc
或collection
方法的末尾,以正确地输入它们。它只需要一个converter
参数。下面我们创建的是一个可重用的“通用转换器”,它接受您选择的接口。所以你把
.withConverter(converter<MyInterfaceHere>())
放在collection
或doc
的末尾,瞧!你就有了类型安全!下面是完整的示例:
现在
userData
有一个Ref<User | null | undefined>
类型,您可以访问它的所有User
属性而不会出错。它是Firestore,具有TypeScript提供的所有类型安全功能!