vue.js - TypeScript + Vue: Hvilken returtype bør brukes for et objekt som inneholder en reactive() og ref() variabel?


Jeg har en Vue 3 komposisjonell funksjon.

Den returnerer et objekt som inneholder én reactive()-variabel og én ref()-variabel.

Og jeg vil gjerne sette en returtype på denne funksjonen for å tilfredsstille en eslint-feil.

Men jeg er ny på Vue og TypeScript og er ikke sikker på hva returtypen skal være.

  • Hvis jeg bruker unknown, kaster TS en feil Object is of type 'unknown'.ts(2571) når jeg kaller funksjonen.
  • Hvis jeg bruker any, klager eslint med en annen feil fordi den ikke liker any-typen
  • Hvis jeg bruker object, klager eslint på at jeg bør bruke <Record<string, unknown> i stedet fordi object for øyeblikket er vanskelig å bruke
  • Hvis jeg bruker <Record<string, unknown> så får jeg en haug med feil på selve funksjonen angående tildelbare typer.

Så hva bør jeg bruke som returtype for useCollection()?

import { ref, reactive, watchEffect } from "vue";
import { projectFirestore } from "@/firebase/config";
import {
  query,
  orderBy,
  onSnapshot,
  DocumentData,
  collection,
} from "firebase/firestore";

const useCollection: any = (collectionPath: string) => { //<-- Need to replace this "any" with something else
  const documentsArray = reactive<Record<string, unknown>[]>([]);
  const error = ref<string | null>(null);
  // references
  const collectionReference = collection(projectFirestore, collectionPath);
  const collectionOrdered = query(
    collectionReference,
    orderBy("createdAt", "desc")
  );
  // updates
  const unsubscribe = onSnapshot(
    collectionOrdered,
    (snapshot) => {
      documentsArray.splice(0);
      snapshot.forEach((doc: DocumentData) => {
        documentsArray.push({ ...doc.data(), id: doc.id });
      });
      error.value = null;
    },
    (err) => {
      console.log(err.message);
      documentsArray.splice(0);
      error.value = err.message;
    }
  );
  watchEffect((onInvalidate) => {
    console.log("watchEffect fired");
    onInvalidate(() => {
      console.log("onInvalidate fired");
      unsubscribe();
    });
  });
  return { documentsArray, error };
};

export default useCollection;

Svar #1

reactive returnerer samme objekttype som gitt, med indre refs som blir pakket ut, noe som kan ignoreres avhengig av spesifisert objekt.

ref returnerer Ref-typen.

For denne funksjonen ville en type være:

(collectionPath: string) => { documentsArray: Record<string, unknown>[] , error: Ref<string | null> }

Det kan være unødvendig å spesifisere typen for useCollection-variabelen fordi den blir utledet fra funksjonen. Returtypen utledes fra den enkeltverdien som returneres, { documentsArray, error }, hvor både documentsArray og error er konstanter som også får sine typer utledet ved tildeling.

Hvis en type trenger å være mer spesifikk enn den som blir tolket, f.eks. når samlingsverdier er kjent, håndteres dette ved hjelp av generiske typer:

const useCollection = <T extends unknown = unknown>(collectionPath: string) => {
  const documentsArray = reactive<Record<string, T>[]>([]);
  const error = ref<string | null>(null);
  ...

const c = useCollection<string | number>(...);

Svar #2

Min fungerer med any, men jeg antar det er på grunn av prosjektreglene dine som eslint eller tsconfig.

Du må definere returtypen din på denne måten.

const useCollection: (collectionPath: string) : { documentsArray: reactive<Record<string, unknown>[]>; error: ref<string | null>; } => { 
     // write your code
}

Eller du kan bruke ved å definere et grensesnitt.

interface CollectionResult {
    documentsArray: reactive<Record<string, unknown>[]>;
    error: ref<string | null>;
}
const useCollection: (collectionPath: string) : CollectionResult => { 
    // write your code
}

Relaterte artikler