vue.js - Kun käytät Piniaa ja TypeScriptiä, miten käytät Actionia tilan (State) asettamiseen?
Minulla on Pinia + TypeScript -store nimeltä user.ts, joka näyttää tältä:
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
},
},
});
Tila on FireBase-käyttäjäobjekti.
Ja haluan päivittää photoURL-kentän käyttämällä setPhotoURL()-toimintoa.
Mutta photoURL aiheuttaa tämän TypeScript-virheen:
Cannot assign to 'photoURL' because it is a read-only property. ts(2540)
Mitä teen väärin?
Onko tämä oikea tapa päivittää tila?
Vastaus #1
Voit poistaa readonly-määreen määrittämällä tyypin uudelleen seuraavasti:
Muokkainten kartoittaminen
On olemassa kaksi lisämääritettä, joita voidaan soveltaa kartoituksen aikana:
readonlyja?, jotka vaikuttavat muokattavuuteen ja valinnaisuuteen vastaavasti.Voit poistaa tai lisätä näitä modifikaattoreita lisäämällä etuliitteen
-tai+. Jos et lisää etuliitettä, oletetaan+.// Removes 'readonly' attributes from a type's properties type CreateMutable<Type> = { -readonly [Property in keyof Type]: Type[Property]; };
Jos tyypillä on sisäkkäisiä ominaisuuksia, jotka haluat olevan kirjoitettavissa, tee kartoitus rekursiivisesti:
type CreateMutable<T> = { -readonly [P in keyof T]: CreateMutable<T[P]> }
Sitten käytä sitä kirjoittaaksesi kaupan user-ominaisuuden:
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
},
},
})
Vastaus #2
'firebase/auth' määrittelee User-rajapinnan omaavan readonly-ominaisuudet. Kun pakotat kyseisen rajapinnan tilamuuttujaasi, TS luottaa sinuun.
Levittäminen pitäisi poistaa readonly sen ominaisuuksista, samalla kun tyypit johdetaan:
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: {
//...
}
})
