Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

411
Vistas
¿Cómo asignar un valor a una referencia que tiene un tipo genérico?

Estoy escribiendo un Vue componible usando TypeScript.

Toma un tipo T genérico y una path de un solo parámetro, y devuelve un document ref.

Casi lo tengo funcionando, pero cada vez que intento asignar un valor a la referencia del document , arroja un error como este:

 Type '{ id: string; }' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to '{ id: string; }'.ts(2322)

Aquí hay una versión recortada del componible:

 import { ref, Ref } from "vue"; import { projectFirestore } from "@/firebase/config"; import { doc, onSnapshot } from "firebase/firestore"; const getDocument = <T>( path: string ): { document: Ref<T | null>; } => { const document = ref(null) as Ref<T | null>; const docRef = doc(projectFirestore, path); onSnapshot(docRef, (doc) => { document.value = { //<-- Error here on "document.value" ...doc.data(), id: doc.id, }; }); return { document }; }; export default getDocument;

No importa lo que asigne a document.value (cadenas, un objeto vacío, etc.), siempre da un error similar que dice que no se puede asignar al tipo T

Entiendo que el error me dice que el tipo T podría ser cualquier cosa y, por lo tanto, no es seguro asignar estas cosas porque el tipo de las cosas podría no ser compatible con el tipo T

Pero como soluciono este problema? ¿Puedo de alguna manera decirle a TypeScript que el tipo T es compatible con otros tipos?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Acabo de descubrir otra solución.

Dado que Firebase proporciona una interfaz DocumentData , la usé en la referencia del document y el tipo de retorno.

Hacerlo me permitió eliminar el genérico T por completo.

Esto hace que sea una función componible mucho más simple sin la necesidad de crear y pasar mis propias interfaces. Resuelve los errores en este componible y los errores en la plantilla Vue SFC cuando se llama.

Aquí está el código completo:

 import { ref, Ref } from "vue"; import { projectFirestore } from "@/firebase/config"; import { doc, onSnapshot, DocumentSnapshot, DocumentData, } from "firebase/firestore"; const getDocument = ( path: string ): { document: Ref<DocumentData | null>; } => { const document = ref<DocumentData | null>(null); const docRef = doc(projectFirestore, path); onSnapshot(docRef, (doc: DocumentSnapshot<DocumentData>) => { if (doc.data()) { document.value = { ...doc.data(), id: doc.id, }; } }); return { document }; }; export default getDocument;
over 4 years ago · Santiago Trujillo Denunciar

0

T solo se usa en su tipo de devolución. Su genérico está declarando que la Ref resultante es la elección de T de la persona que llama sin límites.

Incluso si pudiera especificar que T extends { id: string } o que su tipo de retorno es T & { id: string } y puede hacerlo, usando esa sintaxis), tendría que derrotar la tipificación fuerte en algún momento, porque en tiempo de ejecución getDocument nunca sabrá lo suficiente sobre T para afirmar que doc.data() será compatible con el T particular que infiere la llamada getDocument .

Yo elegiría una de estas tres opciones:

  • Elimina el genérico y devuelve Ref<{id: string} | null> , que es de tipo seguro pero lo obligaría a usar la notación ref["key"] para verificar claves desconocidas arbitrarias.
  • Mantenga lo genérico y confíe en sus llamadas a getDocument para especificar el tipo correcto, pensando que es mucho más probable que su código introduzca errores que que Firestore le proporcione un tipo de datos inesperado. Necesitaría usar as any para mostrar a TypeScript que está eliminando deliberadamente la seguridad de tipos al asignar document.value .
  • Utilice un predicado de tipo que pase a getDocument junto con la ruta. El predicado es una función que tomaría un solo argumento y devolvería si su argumento is T , que podría verificar en onSnapshot para asegurarse de que su document sea seguro para convertir a T o falle con la mitigación/error de su diseño. Esto también restringe T para que su genérico no pueda ser absolutamente de ningún tipo. Vea el ejemplo a continuación.

 const getDocument = <T>( path: string, docPredicate: (doc: any) => doc is T, // accept predicate ): { document: Ref<T & {id: string} | null>; } => { const document = ref(null) as Ref<T & {id: string} | null>; const docRef = doc(projectFirestore, path); onSnapshot(docRef, (doc) => { const data = doc.data(); // extract to local variable if(docPredicate(data)) { // convince TS data is type T document.value = { ...data, // integrate as expected id: doc.id, }; } }); return { document }; }; interface Foo { a: string, b: number } function isFoo(doc: any): doc is Foo { // TODO: check that doc has {a: string, b: number} return true; } const fooDoc = getDocument("bar", isFoo); if (fooDoc.document.value) { console.log(fooDoc.document.value.a); console.log(fooDoc.document.value.id); }

Patio de juegos antes => Patio de juegos después

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda