簡體   English   中英

GraphQL.js-使用接口作為resolveType函數中的默認(備用)類型

[英]GraphQL.js - use Interface as a default (fallback) type in resolveType function

如果提供的類型都不匹配,我試圖在resolveType函數中返回泛型。 下面的示例顯示了此問題:API就像支持UserTypeMovieType一樣工作,直到在數據庫中添加BookType (GraphQL模式不支持)。

const {
  graphql,
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLNonNull,
  GraphQLList,
  GraphQLInterfaceType
} = require("graphql");

const DATA = [
  {
    // UserType
    name: "catherine woolf",
    nick: "catherine"
  },
  {
    // MovieType
    name: "cat woman",
    director: "Jack Wolfgang"
  },
  {
    // --- missing type --- (BookType)
    name: "cats secrets",
    author: "Nicky Glace"
  }
];

const resolveType = data => {
  if (data.nick) {
    return UserType;
  }
  if (data.director) {
    return MovieType;
  }
};

const SearchableType = new GraphQLInterfaceType({
  name: "Searchable",
  fields: {
    name: { type: GraphQLString }
  },
  resolveType: resolveType
});

const UserType = new GraphQLObjectType({
  name: "User",
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
    nick: { type: GraphQLString }
  }
});

const MovieType = new GraphQLObjectType({
  name: "Movie",
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
    director: { type: GraphQLString }
  }
});

const schema = new GraphQLSchema({
  types: [MovieType, UserType, SearchableType],
  query: new GraphQLObjectType({
    name: "RootQueryType",
    fields: {
      search: {
        type: new GraphQLList(SearchableType),
        args: {
          text: { type: new GraphQLNonNull(GraphQLString) }
        },
        resolve(_, { text }) {
          return DATA.filter(d => d.name.indexOf(text) !== -1);
        }
      }
    }
  })
});

const query = `
  {
    search(text: "cat") {
      name
      ... on User {
        nick
      }
      ... on Movie {
        director
      }
    }
  }
`;

graphql(schema, query).then(result => {
  console.log(JSON.stringify(result, null, 2));
});

所以現在這段代碼以錯誤結尾:

“抽象類型Searchable必須在運行時解析為值為RootQueryType.search的對象類型,其值為\\“ [object Object] \\”,接收為\\“ undefined \\”。Searchable類型應提供一個\\“ resolveType \\”函數,或者每個可能的類型應提供\\“ isTypeOf \\”函數。

這不足為奇,因為當前resolveType可能不返回任何類型。

解決方法

板條箱類型包含相同的字段,例如接口SearchableType (1對1的實現):

const _SearchableType = new GraphQLObjectType({
  name: '_Searchable',
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
  }
});

使用它作為后備類型:

const resolveType = data => {
  if (data.nick) {
    return UserType;
  }
  if (data.director) {
    return MovieType;
  }
  return _SearchableType;
};

並將其添加到schema定義中的types

types: [MovieType, UserType, SearchableType, _SearchableType],

但是此解決方案的問題是這樣的偽_SearchableType在如下文檔中的存在:

文檔中有問題的_SearchableType

有什么方法可以返回接口SearchableTyperesolveType等效接口嗎? 對我而言,關鍵點是在文檔中隱藏了這種“后備類型”。

GraphQL是強類型的,在解決聯合和接口時不支持泛型或某種“后備”機制。 歸根結底,如果您的基礎數據層返回的是您尚未在架構中實現的某種類型,那么最簡單的解決方案是將該類型添加到架構中。 遷移到數據庫和更改架構應該同時進行。

如果要從存儲層派生架構,建議您使用PostGraphile (以前稱為PostGraphQL)之類的工具。

就是說,如果您打算使用一種解決方法,則可以使用現有類型之一:

const resolveType = data => {
  if (data.nick) {
    return UserType
  }
  return MovieType
}

現在,只要您在界面(而不是其中一種類型)上進行查詢,一本書的名稱仍然可以訪問。 這種方法的唯一缺點是,將為書籍返回特定於電影的字段,並將其解析為null,但這不會引起任何問題,除非在您的模式中將它們明確定義為非null。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM