es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Typescript + GraphQL Dataloader más tipos estrictos utilizando genéricos o sobrecargas.

Estoy usando el dataloader de GraphQL y me gustaría hacer que mis tipos de retorno sean más estrictos en función de las claves que se pasen. ¿Cómo podría lograr esto? Intento débil a continuación. Sé por qué no funciona, pero no estoy seguro de qué arreglar. (El mismo código existe en el playground de ts [aquí].(https://www.typescriptlang.org/play?ssl=27&ssc=2&pln=1&pc=1#code/C4TwDgpgBAYgTgVwJbAHIEMC20C8UDk6YYANhPlAD4EBG6Adg+vgFCiSyIoDSEIAPABUM2KBAAewCPQAmAZ07I0WCAD4oeAN6NsALijCVAGihIZ++gkw0IcAL5tw0AILEyGgs9btoAISaMHvi+rCxI9FJwAGboAMbQ8EoAaugkCBAKmixQUESkEPqu+dlQdIyM+v7l6CwOLDIQsSTocNBN6HIKACLowOgAMgD26A1w-NwmSepZOSTDMgAUANZ8+twAlPpJtSwsUQj0scBIg-RQAOYQwEMjtkJiktLyiigiagvrUDNQAPQ-BgALJAKGSDDL0fDAKAAd0GcCWJhoCChKHwCmAAOg52GJAAtLioAg5NAMdBBBdpLYkLEoMBBlA5ADBtDaZioK1msdToykGBSldoRBpFAViAoAAyKAAN1S6QAdFASq1gAg4Gd6BAWT0+jdRvxEjw+EJVCYDcAUmkMgBtQQAXVUHx2ewORxOZ0w6HCHy+JVi3KhUS413mtg8l2DtzgjpyfygAHEkFLhRjeqzoDpoMCCHkyPgTKT2VdVWcfAymQgSDJ+VAimREcjTCiFLXoNQqkwcr7-bk3LgoIGlLrbHK5iMFtoVPpCL286ZzFAAIx2da7GP-BNJksA1MFjOmBT4MpMWcF5XF2lOMuDCtVmxQduBRU5P30ORQo+BPADlBDuAj+bjhmU4fswJhmPoABMy47DkQA))

“`ts
type FruitName = 'apple' | 'banana'
type FruitKey<tname extends="" fruitname=""> = {name: TName, id: number}
type Apple = 'A'
type Banana = 'B'

interface FruitValues {
apple: Apple
banana: Banana
}

declare class DataLoader<k, v=""> {
load(key: K): V
}

function getLoader<t extends="" fruitname="">() {
// Esto no funciona, pero es el objetivo: usar el genérico T para mostrar la relación entre la clave y el valor.
return new DataLoader<><t>, FruitValues[T]>()
}

function main() {
const fruitLoader = getLoader()
// Dado que el nombre es 'apple', el tipo de retorno debería ser Apple, pero es Apple | Banana
const apple = fruitLoader.load({name: 'apple', id: 1})

// Dado que el nombre es 'banana', el tipo de retorno debería ser Banana
const banana = fruitLoader.load({name: 'banana', id: 2})
}
“`</k,>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para hacer que los tipos de retorno sean más estrictos en función de las claves que se pasan al usar el dataloader de GraphQL, los tipos genéricos para la clase DataLoader se pueden modificar de la siguiente manera:

    type FruitName = 'apple' | 'banana';
    type FruitKey<tname extends="" fruitname=""> = {name: TName, id: number};
    
    interface FruitValues {
      apple: 'A';
      banana: 'B';
    }
    
    declare class DataLoader<k extends=""></k><fruitname>, V> {
      load(key: K): V;
    }
    
    function getLoader<t extends="" fruitname="">(name: T) {
      if (name === 'apple') {
        return new DataLoader<><t>, FruitValues['apple']>();
      } else if (name === 'banana') {
        return new DataLoader<><t>, FruitValues['banana']>();
      }
    }
    
    function main() {
      const appleLoader = getLoader('apple');
      const apple = appleLoader.load({name: 'apple', id: 1});
      // apple ahora es de tipo 'A'
    
      const bananaLoader = getLoader('banana');
      const banana = bananaLoader.load({name: 'banana', id: 2});
      // banana ahora es de tipo 'B'
    }
    

    En lugar de usar el tipo genérico T para especificar el nombre de la fruta, se pasa como argumento a la función getLoader. La clase DataLoader ahora se define con dos tipos genéricos: K extiende FruitKey para asegurarse de que la propiedad name coincida con uno de los nombres de frutas, y V es el tipo de valor del nombre de fruta correspondiente en la interfaz FruitValues.

    La función getLoader ahora devuelve la instancia apropiada de DataLoader según el nombre de la fruta pasado como argumento. El método load puede ser llamado con un objeto FruitKey cuya propiedad name coincida con la instancia correspondiente de DataLoader, y el tipo de retorno será el tipo de valor del nombre de fruta correspondiente en la interfaz FruitValues.

Comments are closed.