I am using the graphql-request library to fetch data froma GraphQL endpoint.
The endpoint returns some information about a user, based on a certain token associated to that user.
Here is the type I’ve defined:
export type PlayerInfo = {
country: string,
name: string|undefined,
email: string,
id: string,
}
Here are the two approaches I’ve tried so far (represented by the two functions getUserInfoOld
and getUserInfo
):
import { gql, GraphQLClient, request } from 'graphql-request'
import { PlayerInfo } from './AuthClientInterface'
import type { TypedDocumentNode } from '@graphql-typed-document-node/core'
import { parse } from 'graphql'
type UserInfoResponse = {
getUserInfo: {
country: string,
name: string|undefined,
email: string,
id: string,
}
}
class GraphQLClient {
async getUserInfoOld(token: string): Promise<PlayerInfo> {
const query = gql`
query GetUserInfo($input: userInfoInput) {
getUserInfo(input: $input) {
country
email
id
name
}
}
`
const input = {
"input": {
"accessToken": token
}
}
const host = 'https://host.example/'
const gqClient = new GraphQLClient(host)
const result = await gqClient.request(query, input) as any // this works but I don't like it
return result.getUserInfo as PlayerInfo
}
async getUserInfo(token: string): Promise<PlayerInfo> {
const host = 'https://host.example/'
const query: TypedDocumentNode<{ getUserInfo: UserInfoResponse }, Record<any, any>> = parse(gql`
query GetUserInfo($input: userInfoInput) {
getUserInfo(input: $input) {
country
email
id
name
}
}
`)
const input = {
"input": {
"accessToken": token
}
}
const data = await request(host, query, input)
return data.getUserInfo as PlayerInfo // this does not work: why?
return data.getUserInfo as any // this works but I would like to avoid it
}
}
export default GraphQLClient
Now, the first approach in works, but I don’t like it because I find it’s very much against Typescript’s whole concept to just cast any
into the proper type, and just hope that it works.
Whic is why, after taking a look at this example, I tried working with TypedDocumentNode
, adn tried creating an appropriate response type UserInfoResponse
which then could be cast as PlayerInfo
.
Note that when I add console.log(data.getUserInfo)
right before the return statement of the second function, I see exactly what I would need:
{
country: 'DE',
email: '[email protected]',
id: '12345678',
name: 'John Doe'
}
So I don’t get why Typescript is giving me this error when I try to do return data.getUserInfo as PlayerInfo
, when data.getUserInfo
contains indeed the right fields:
Conversion of type 'UserInfoResponse' to type 'PlayerInfo' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'UserInfoResponse' is missing the following properties from type 'PlayerInfo': country, name, email, id
I even tried changing the UserInfoResponse
type to
type UserInfoResponse = {
getUserInfo: PlayerInfo
}
but this didn’t help either.
What am I missing or doing wrong here?