vue.js - Pinia ve TypeScript kullanırken, bir Action ile State nasıl ayarlanır?


user.ts adında bir Pinia + TypeScript mağazam var ve şu şekilde görünüyor:

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
    },
  },
});

Durum bir FireBase Kullanıcı nesnesidir.

Ve setPhotoURL() eylemini kullanarak photoURL'yi güncellemek istiyorum.

Ama photoURL bu TypeScript hatasına sahip:

Cannot assign to 'photoURL' because it is a read-only property. ts(2540)

Ben neyi yanlış yapıyorum?

Durumu güncellemenin doğru yolu bu mu?

Cevap #1

Türü eşleyerek readonly değiştiricisini kaldırabilirsiniz :

Değiştiricileri Eşleme

Eşleme sırasında uygulanabilecek iki ek değiştirici vardır: readonly ve ?; bunlar sırasıyla değiştirilebilirlik ve isteğe bağlılığı etkiler.

Bu değiştiricileri başına - veya + ekleyerek kaldırabilir veya ekleyebilirsiniz. Bir önek eklemezseniz, + varsayılır.

// Removes 'readonly' attributes from a type's properties
type CreateMutable<Type> = {
  -readonly [Property in keyof Type]: Type[Property];
};

Eğer türün yazılabilir olmasını istediğiniz iç içe geçmiş özellikleri varsa, özyinelemeli olarak eşleştirin:

type CreateMutable<T> = { -readonly [P in keyof T]: CreateMutable<T[P]> }

Sonra bunu mağazanın user özelliğini yazmak için kullanın:

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
    },
  },
})

Cevap #2

'firebase/auth', User ara yüzünü readonly özelliklere sahip olarak bildirir. Bu ara yüzü durum nesnenize zorla uygularsanız, TS size güvenir.

Bunu yaymak, tipleri yine de türetirken, readonly'i özelliklerinden kaldırmalıdır:

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: {
    //...
  }
})