1. ホーム
  2. typescript

[解決済み] Apollo Serverでコンテキストオブジェクトを正しく入力するにはどうすればよいですか?

2022-02-16 06:17:54

質問事項

を使っています。 APOLLOサーバー をtypescriptで記述した場合、リゾルバ内のコンテキストパラメータに name プロパティの context は文字列です。今は、次のように入力されています。 any と入力したい。 string . また context パラメータは、特定のインターフェイスであって欲しいのに、anyタイプになっています。コンテキストとそのプロパティに、どのような型にしたいかを伝える方法はないでしょうか。 any ?

const server = new ApolloServer({
  typeDefs: gql`
    type Query {
      test: String
    }
  `,
  resolvers: {
    Query: {
      test(parent: any, args: any, context, info: any) {
        context.name // name is typed as "any" when I'd like it to be typed as "string"
      }
    }
  },
  context() {
    return { 
      name: 'John Doe' 
    }
  }
})

こんな感じでやってみたんですが、これだとエラーが出ますね。

context<{ name: string }>() {
  return { 
    name: 'John Doe' 
  }
}

コンテキストに必要なものを明示的に伝えることで動作させることはできましたが、この方法では Context をすべてのリゾルバファイルに追加し、手動でキャストしています。

interface Context {
  name: string
}

const server = new ApolloServer({
  ...
  resolvers: {
    Query: {
      test(parent: any, args: any, context: Context, info: any) {
        context.name // name is typed as "string" here because I used "context: Context" explicitly
      }
    }
  }
  ...
})

解決方法は?

デフォルトでは resolvers フィールドの Config オブジェクトに与えます。 ApolloServer はどんな型にも対応していますが、TypeScriptを使って独自の型の絞り込みを行うことができます。

参考までに ApolloServer のインスタンスまたは配列を受け取ります。 IResolvers オブジェクトを指定します。 https://github.com/apollographql/apollo-server/blob/a241d34e9275bf6a23cf7aa3ddee57f90de7b364/packages/apollo-server-core/src/types.ts#L90 . IResolvers は一般的な型パラメータを持ちますが、それらのデフォルトはanyです。 https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L298 . あなたのコードサンプルでは Query を構成する特定の型の一つである。 IResolverstest() を実装しています。 IFieldResolver : https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L236 .

ということを利用することができます。 IResolvers の型を制限するためのジェネリックパラメータがあります。 context の引数になります。例えば、代入の左辺で明示的に型を指定することで、右辺で何を期待するかをコンパイラに伝えることができる。

interface Context {
  username: string
}

const myResolvers: IResolvers<any, Context> = {
  Query: {
    test: (parent, args, context) => {
      console.log(context.username) // based on generics TS knows context is supposed to be of type Context
    }
  }
}

new ApolloServer({
  ...
  resolvers: myResolvers,
  ...