TypeScript 类型与 GraphQL 类型冲突。

huangapple go评论63阅读模式
英文:

TypeScript Types conflict with graphql types

问题

I have a GraphQL resolver and schema that look like this:

import { Resolvers } from "../../generated/schema";

export const resolvers: Resolvers = {
  Query: {
    getS: async (_parent: unknown, { id }: { id: string }): Promise<GenericResponse<S>> => { ... }
    }
}

and

type Query {
  getS(id: ID!): getSResponse
}

type S {
  id: ID!,
  wac: Float!,
  beginDate: String!,
  endDate: String!,
}

type getSResponse implements GenericResponse {
  status: Status!
  data: S!
}

I'm using GraphQL codegen to check types for resolver functions with the following contents:

export type Resolvers<ContextType = any> = {
  Query?: QueryResolvers<ContextType>;
}

export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
getS?: Resolver<Maybe<ResolversTypes['getSResponse']>, ParentType, ContextType, RequireFields<QueryGetSArgs, 'id'>>;
}

export type QueryGetSArgs = {
  id: Scalars['ID']['input'];
};

export type Scalars = {
  ID: { input: string | number; output: string; }
  String: { input: string; output: string; }
  Boolean: { input: boolean; output: boolean; }
  Int: { input: number; output: number; }
  Float: { input: number; output: number; }
};

However, I am getting this TypeScript error:

Type '(_parent: unknown, { id }: myType) => Promise<GenericResponse<S>>' is not assignable to type 'Resolver<Maybe<ResolverTypeWrapper<GetWacPercentageResponse>>, {}, any, RequireFields<QueryGetSArgs, "id"> | undefined>'.
  Type '(_parent: unknown, { id }: myType) => Promise<GenericResponse<S>>' is not assignable to type 'ResolverFn<Maybe<ResolverTypeWrapper<GetSResponse>>, {}, any, RequireFields<QueryGetSArgs, "id">>'.
    Types of parameters '__1' and 'args' are incompatible.
      Type 'RequireFields<QueryGetSArgs, "id">' is not assignable to type 'myType'.
        Types of property 'id' are incompatible.
          Type 'NonNullable<string | number>' is not assignable to type 'string'.
            Type 'number' is not assignable to type 'string'.ts(2322)

How can I fix this?

英文:

I have a GraphQL resolver and schema that look like this:

import { Resolvers } from &quot;../../generated/schema&quot;;

export const resolvers: Resolvers = {
  Query: {
    getS: async (_parent: unknown, { id }: { id: string }): Promise&lt;GenericResponse&lt;S&gt;&gt; =&gt; { ... }
    }
}

and

type Query {
  getS(id: ID!): getSResponse
}

type S {
  id: ID!,
  wac: Float!,
  beginDate: String!,
  endDate: String!,
}

type getSResponse implements GenericResponse {
  status: Status!
  data: S!
}

I'm using GraphQL codegen to check types for resolver functions with the following contents:

export type Resolvers&lt;ContextType = any&gt; = {
  Query?: QueryResolvers&lt;ContextType&gt;;
}

export type QueryResolvers&lt;ContextType = any, ParentType extends ResolversParentTypes[&#39;Query&#39;] = ResolversParentTypes[&#39;Query&#39;]&gt; = {
getS?: Resolver&lt;Maybe&lt;ResolversTypes[&#39;getSResponse&#39;]&gt;, ParentType, ContextType, RequireFields&lt;QueryGetSArgs, &#39;id&#39;&gt;&gt;;
}

export type QueryGetSArgs = {
  id: Scalars[&#39;ID&#39;][&#39;input&#39;];
};

export type Scalars = {
  ID: { input: string | number; output: string; }
  String: { input: string; output: string; }
  Boolean: { input: boolean; output: boolean; }
  Int: { input: number; output: number; }
  Float: { input: number; output: number; }
};

However, I am getting this typescript error:

Type &#39;(_parent: unknown, { id }: myType) =&gt; Promise&lt;GenericResponse&lt;S&gt;&gt;&#39; is not assignable to type &#39;Resolver&lt;Maybe&lt;ResolverTypeWrapper&lt;GetWacPercentageResponse&gt;&gt;, {}, any, RequireFields&lt;QueryGetSArgs, &quot;id&quot;&gt;&gt; | undefined&#39;.
  Type &#39;(_parent: unknown, { id }: myType) =&gt; Promise&lt;GenericResponse&lt;S&gt;&gt;&#39; is not assignable to type &#39;ResolverFn&lt;Maybe&lt;ResolverTypeWrapper&lt;GetSResponse&gt;&gt;, {}, any, RequireFields&lt;QueryGetSArgs, &quot;id&quot;&gt;&gt;&#39;.
    Types of parameters &#39;__1&#39; and &#39;args&#39; are incompatible.
      Type &#39;RequireFields&lt;QueryGetSArgs, &quot;id&quot;&gt;&#39; is not assignable to type &#39;myType&#39;.
        Types of property &#39;id&#39; are incompatible.
          Type &#39;NonNullable&lt;string | number&gt;&#39; is not assignable to type &#39;string&#39;.
            Type &#39;number&#39; is not assignable to type &#39;string&#39;.ts(2322)

How can I fix this?

答案1

得分: 2

你的ID显然可以是一个stringnumber

ID: { input: string | number; output: string; }

但是你的解析器参数将其强类型化为string,这是一个问题,因为根据你的标量定义,解析器可以接收一个数字。你需要使其可以使用stringnumber

getS: async (_parent: unknown, { id }: { id: string | number }): Promise<GenericResponse<S>> => { ... }

但老实说,由于你已经将Resolvers类型分配给整个resolvers对象,你应该能够完全删除内联类型,它将被推断出来:

getS: async (_parent, { id }) => { ... } // `id` 应该会自动推断为string | number
英文:

Your ID can apparently be a string or number:

  ID: { input: string | number; output: string; }

But your resolver argument has it strongly typed to a string which TS correctly points out as an issue because that resolver can receive a number as per your scalar definition of ID. You need to make that work with string or number

getS: async (_parent: unknown, { id }: { id: string | number }): Promise&lt;GenericResponse&lt;S&gt;&gt; =&gt; { ... }

But to be honest, since you already assign Resolvers type to the whole resolvers object you should just be able to completely remove the inline types and it will be inferred:

getS: async (_parent, { id }) =&gt; { ... } // `id` should automatically be inferred as string | number

答案2

得分: 1

你有

类型 查询 {
获取S(id: ID!): 获取S响应
}

说“获取S”将接受类型为“ID = 数字或字符串”的“id”。但是你的解析器实现如下

查询: {
获取S: async (_parent: unknown, { id }: { id: string }): Promise&lt;GenericResponse&lt;S&gt;&gt; =&gt; { ... }
}

说它只接受类型为“字符串”的“id”。

显然这里有矛盾。你可能想将解析器参数更改为{ id: string | number }

英文:

You have

type Query {
getS(id: ID!): getSResponse
}

Saying getS would accept id of type ID = number or string. But your resolver implementation goes like

Query: {
getS: async (_parent: unknown, { id }: { id: string }): Promise&lt;GenericResponse&lt;S&gt;&gt; =&gt; { ... }
}

saying it would ONLY take id of type string.

Obviously there’s a contradiction here. You probably want to change your resolver param to { id: string | number }.

huangapple
  • 本文由 发表于 2023年6月16日 06:09:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76485811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定