Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can't use __typename inside async function #3610

Closed
ghost opened this issue Mar 9, 2020 · 8 comments
Closed

can't use __typename inside async function #3610

ghost opened this issue Mar 9, 2020 · 8 comments
Assignees
Labels

Comments

@ghost
Copy link

ghost commented Mar 9, 2020

Describe the bug
I get Type error when I try to use __typename inside async function

  1. this work fine
const signInWithEmail: MutationResolvers["signInWithEmail"] = () => {
    return {
        __typename: "LoginResponse",
        token: "token"
    }
}

but here when I add async I get the error

const signInWithEmail: MutationResolvers["signInWithEmail"] = async () => {
    return {
        __typename: "LoginResponse",
        token: "token"
    }
}

The error

TS2322: Type '() => Promise<{ __typename: string; token: string; }>' is not assignable to type 'ResolverFn<LoginResponse | UserError | Promise<LoginResponse> | Promise<UserError>, {}, any, RequireFields<MutationSignInWithEmailArgs, "input">> | StitchingResolver<...> | undefined'.
   Type '() => Promise<{ __typename: string; token: string; }>' is not assignable to type 'ResolverFn<LoginResponse | UserError | Promise<LoginResponse> | Promise<UserError>, {}, any, RequireFields<MutationSignInWithEmailArgs, "input">>'.
     Type 'Promise<{ __typename: string; token: string; }>' is not assignable to type 'LoginResponse | UserError | Promise<LoginResponse> | Promise<UserError> | Promise<LoginResponse | UserError | Promise<...> | Promise<...>>'.
       Type 'Promise<{ __typename: string; token: string; }>' is not assignable to type 'Promise<LoginResponse>'. 
         Type '{ __typename: string; token: string; }' is not assignable to type 'LoginResponse'.
           Types of property '__typename' are incompatible.
             Type 'string' is not assignable to type '"LoginResponse" | undefined'.
  1. My GraphQL schema:
    input SignInInfo {
        email: String!
        password: String!
    }
    type LoginResponse {
        token: String!
    }

    union SignInResult = LoginResponse | UserError

    type Mutation {
        signInWithEmail(input: SignInInfo!): SignInResult!
    }

    type UserError {
        message: String!
    }
  1. My codegen.yml config file:
overwrite: true
schema: "http://localhost:4000/"

documents: null
generates:
  src/generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-resolvers"
    config:
      useIndexSignature: true

Expected behavior

Environment:

  • OS: Ubuntu 19.10
  • "@graphql-codegen/cli": "^1.12.2"
  • "@graphql-codegen/typescript": "1.12.2"
  • "@graphql-codegen/typescript-resolvers": "^1.12.2"
  • NodeJS: 13.6.0
@dotansimha
Copy link
Owner

@kamilkisiela can you please take a look?

@kamilkisiela
Copy link
Collaborator

@dotansimha I don't think there's something we could do... It's TypeScript that has no idea how to compare a string with an actual value.

adding as const will solve the problem on consumer-side.

@moun3iim In your example, if you set "LoginResponse" as const then it will treat it as a value not as a string.

This type of annotation is called const assertions. Here's more about the problem: https://devblogs.microsoft.com/typescript/announcing-typescript-3-4-rc/. It's available since TypeScript 3.4.

@dotansimha another solution but more "painful" to developers could be to let typescript-resolvers generate enum Typename { LoginResponse = 'LoginResponse' ... } and make all signatures expect an enum value. Then in resolvers instead of using __typename: 'LoginResponse' you use __typename: Typename.LoginResponse.

@dotansimha
Copy link
Owner

@kamilkisiela we can generate const assertions in base typescript already, it's done by @DragorWW in #3569 , is it enough for that? or something is still missing?

@ghost
Copy link
Author

ghost commented Mar 15, 2020

@dotansimha I don't think there's something we could do... It's TypeScript that has no idea how to compare a string with an actual value.

adding as const will solve the problem on consumer-side.

@moun3iim In your example, if you set "LoginResponse" as const then it will treat it as a value not as a string.

This type of annotation is called const assertions. Here's more about the problem: https://devblogs.microsoft.com/typescript/announcing-typescript-3-4-rc/. It's available since TypeScript 3.4.

@dotansimha another solution but more "painful" to developers could be to let typescript-resolvers generate enum Typename { LoginResponse = 'LoginResponse' ... } and make all signatures expect an enum value. Then in resolvers instead of using __typename: 'LoginResponse' you use __typename: Typename.LoginResponse.

I can't understand, should I edit "LoginResponse" in the generated file !!

@dotansimha
Copy link
Owner

dotansimha commented Mar 16, 2020

@moun3iim no, you should add it to the code you are writing :)

const signInWithEmail: MutationResolvers["signInWithEmail"] = async () => {
    return {
        __typename: "LoginResponse" as const, // < here
        token: "token"
    }
}

@joeyfigaro
Copy link

Looks like this is no longer working with TS 4.0.2–using "ResultName" as const does not remove the error; like OP, though, removing async does remove the error.

@dotansimha
Copy link
Owner

It makes sense, since it marks the function as real async function, and not just as a regular function that returns a Promise.
@joeyfigaro any example for the TS4.2 issue? how can I reproduce this?

@joeyfigaro
Copy link

Fair questions @dotansimha — I think my issue is unrelated to the issue described here. I'm going to open up a new ticket with a repro. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants