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 feilObject is of type 'unknown'.ts(2571)når jeg kaller funksjonen. - Hvis jeg bruker
any, klager eslint med en annen feil fordi den ikke likerany-typen - Hvis jeg bruker
object, klager eslint på at jeg bør bruke<Record<string, unknown>i stedet fordiobjectfor ø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
}
