typescript - GraphQLServer tipuri union "Tip abstract N trebuie să fie rezolvat la un tip Obiect la execuție" eroare


Având un tip de returnare union în GraphQL:

union GetBankAccountsResponseOrUserInputRequest = GetAccountsResponse | UserInputRequest

destinat să fie returnat de un anumit rezolvator:

type Query {
  getBankAccounts: GetBankAccountsResponseOrUserInputRequest!
}

Primesc aceste avertismente sau erori referitoare la o funcție __resolveType sau __isTypeOf:

Abstract type N must resolve to an Object type at runtime for field Query.getBankAccounts with value { ..., __isTypeOf: [function __isTypeOf] }, received "undefined". Either the N type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.'

Am căutat zile întregi în problemele de pe GitHub și în întrebările de pe Stack Overflow încercând să rezolv această eroare.

Implementarea __resolveType sau __isTypeOf în rezolvatoarele mele nu funcționează:

export const Query = {
  getBankAccounts: (parent, args, context: IContext, info) => {
    return {
      __isTypeOf(obj) { // OR __resolveType, none of them work
        return `GetAccountsResponse`;
      },
      accounts: []
    };
  },
};

Răspuns #1

Deoarece implementarea __resolveType sau __isTypeOf în resolverele mele nu a funcționat pentru mine, am ajuns să rezolv această problemă adăugând __typename direct în obiectul returnat de resolver.

În implementarea rezolvatorului getBankAccounts:

async getBankAccounts(): GetBankAccountsResponseOrUserInputRequest {
    if (shouldGetUserInputRequest()) {
      return {
        __typename: "UserInputRequest",
        ...response,
      };
    }

    return {
      __typename: "GetAccountsResponse",
      accounts,
    };
  }

Sper că acest lucru ajută pe cineva.

Răspunsul #2

Harta ta de rezolvare nu este configurată corect.

Harta resolverului transmisă către ApolloServer (sau makeExecutableSchema) ar trebui să fie un obiect ale cărui chei sunt numele tipurilor din schema ta, fiecare cheie mapând către un alt obiect ale cărui chei sunt numele câmpurilor pentru acel tip. Fiecare nume de câmp apoi se mapează la o funcție resolver.

const resolvers = {
  SomeType: {
    someField: (parent, args, context, info) => { ... },
  },
}

Folosești aceeași hartă de rezolvare pentru a transmite funcția resolveType pentru o uniune sau o interfață. Modelul este același, dar numele tipului este numele uniunii sau interfeței și, în loc de un nume de câmp, cheia este __resolveType:

const resolvers = {
  SomeType: {
    someField: (parent, args, context, info) => { ... },
  },
  SomeUnion: {
    __resolveType: (parent) => { ... },
  }
}

Funcția resolveType ar trebui să returneze întotdeauna un șir care corespunde numelui unui tip de obiect existent în schema ta.

Dacă folosești __isTypeOf în loc de __resolveType, atunci acest lucru va arăta puțin diferit pentru că funcția isTypeOf este asociată cu un anumit tip de obiect, nu cu interfața sau uniunea. Toate acestea sunt prezentate în documentație. Deci, harta resolverului arată astfel:

const resolvers = {
  SomeType: {
    someField: (parent, args, context, info) => { ... },
    __isTypeOf: (parent) => { ... },
  },
}

__isTypeOf ar trebui să returneze întotdeauna fie true, fie false, în funcție de faptul dacă obiectul transmis este, de fapt, de acel tip.

Trebuie să folosești doar __resolveType sau __isTypeOf. Dacă folosești __isTypeOf, trebuie să îl adaugi la fiecare tip de obiect posibil din uniune sau interfață.