我有一个名为user.ts
的Pinia+TypeScript存储,看起来像这样:
import { User } from 'firebase/auth';
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () =>
({
displayName: null,
email: null,
emailVerified: null,
isAnonymous: null,
metadata: null,
multiFactor: null,
phoneNumber: null,
photoURL: null,
providerData: null,
providerId: null,
refreshToken: null,
tenantId: null,
uid: null,
} as unknown as User),
actions: {
setPhotoURL(photoURLData: string | null) {
this.photoURL = photoURLData; //<-- ERROR HERE
},
},
});
状态是FireBase User对象。
我想使用setPhotoURL()
操作来更新photoURL
。
但是photoURL
有这个TypeScript错误:
Cannot assign to 'photoURL' because it is a read-only property. ts(2540)
我做错了什么?
这是更新状态的正确方式吗?
您可以通过映射类型来移除readonly
修饰符:
映射修改器
映射过程中可以应用两个额外的修饰符:
readonly
和?
,它们分别影响可变性和可选性。您可以通过前缀
-
或+
来删除或添加这些修饰符。如果不添加前缀,则假定为+
。// Removes 'readonly' attributes from a type's properties type CreateMutable<Type> = { -readonly [Property in keyof Type]: Type[Property]; };
如果类型具有您希望可写的嵌套属性,则递归映射:
type CreateMutable<T> = { -readonly [P in keyof T]: CreateMutable<T[P]> }
然后使用它键入商店的user
属性:
import type { User } from 'firebase/auth'
import { defineStore } from 'pinia'
type CreateMutable<T> = { -readonly [P in keyof T]: CreateMutable<T[P]> }
export const useUserStore = defineStore('user', {
state: () => ({ user: {} as CreateMutable<User> }),
actions: {
setPhotoURL(photoURLData: string | null) {
this.user.photoURL = photoURLData
},
},
})
'firebase/auth'
声明用户界面具有readonly
道具。当您将该接口强制应用于状态对象时,TS信任您。
传播它应该会从道具中移除readonly
,同时仍然推断类型:
export const useUserStore = defineStore('user', {
state: () => ({ ...({
displayName: null,
email: null,
emailVerified: null,
isAnonymous: null,
metadata: null,
multiFactor: null,
phoneNumber: null,
photoURL: null,
providerData: null,
providerId: null,
refreshToken: null,
tenantId: null,
uid: null,
} as unknown as User) }),
actions: {
//...
}
})