Skip to content
This repository has been archived by the owner on May 7, 2023. It is now read-only.

Union type generated by relay-compiler is not compatible with enum type generated by codegen #150

Closed
smallbee3 opened this issue Jul 2, 2020 · 1 comment
Assignees

Comments

@smallbee3
Copy link
Contributor

smallbee3 commented Jul 2, 2020

Specify project

Server

To Reproduce

  1. Remove below code in client/src/App.tsx
// @ts-ignore ==> TODO
  1. Type this in the terminal
$ cd client
$ yarn tsc
  1. See the error

Expected behavior

No error when running yarn tsc

Screenshots

image

Describe the bug

There is a type error in the below code.

// client/src/App.tsx

const initUser = async (me: AppUserQueryResponse['me']): Promise<void> => {
  if (!me) return;
  await initializeEThree(me.id);
  setUser(me);
};

The error occurs in setUser(me); because the type of argument me is not compatible with the type of setUser func's argument.

A) The type of argument me

type AppUserQueryResponse['me']

// src/__generated__/AppUserQuery.graphql.ts

export type AppUserQueryResponse = {
    readonly me: {
        readonly id: string;
        readonly email: string | null;
        readonly verified: boolean | null;
        readonly profile: {
            readonly authType: AuthType;
        } | null;
    };
};

-> type AuthType

// src/__generated__/AppUserQuery.graphql.ts

export type AuthType = "apple" | "email" | "facebook" | "google" | "%future added value";

B) the type of setUser func's argument

type User

// src/providers/AuthProvider.tsx

const setUser = (dispatch: React.Dispatch<SetUserAction>) => (
  authUser: User,
): void => {
  if (!authUser) Relay.init();
  dispatch({
    type: ActionType.SetUser,
    payload: { user: authUser, relay: Relay.environment },
  });
};
// src/types/graphql.ts

export type User = {
  __typename?: 'User';
  id: Scalars['String'];
  email?: Maybe<Scalars['String']>;
  name?: Maybe<Scalars['String']>;
  nickname?: Maybe<Scalars['String']>;
  thumbURL?: Maybe<Scalars['String']>;
  photoURL?: Maybe<Scalars['String']>;
  birthDay?: Maybe<Scalars['DateTime']>;
  gender?: Maybe<Scalars['Gender']>;
  phone?: Maybe<Scalars['String']>;
  statusMessage?: Maybe<Scalars['String']>;
  verified?: Maybe<Scalars['Boolean']>;
  lastSignedIn?: Maybe<Scalars['DateTime']>;
  isOnline?: Maybe<Scalars['Boolean']>;
  createdAt?: Maybe<Scalars['DateTime']>;
  updatedAt?: Maybe<Scalars['DateTime']>;
  deletedAt?: Maybe<Scalars['DateTime']>;
  profile?: Maybe<Profile>;
  notifications?: Maybe<Array<Notification>>;
};

-> type AuthType

// src/types/graphql.ts

export enum AuthType {
  email = 'email',
  facebook = 'facebook',
  google = 'google',
  apple = 'apple'
}


As you can see A) AuthType in src/__generated__/AppUserQuery.graphql.ts is union type, but B) AuthType in src/types/graphql.ts is enum type, which makes an error since union type is not compatible with enum type.

As we know the problem, we could simply check there is no error occurred if we change AuthType's type from union to enum.

// src/__generated__/AppUserQuery.graphql.ts

// export type AuthType = "apple" | "email" | "facebook" | "google" | "%future added value";
export enum AuthType {
    email = 'email',
    facebook = 'facebook',
    google = 'google',
    apple = 'apple'
  }
$ yarn tsc
yarn run v1.22.4
$ tsc
✨  Done in 5.65s.

Unfortunately, AppUserQuery.graphql.ts is generated by relay-compiler library, which means we should not change it manually.
And it seems that this default behavior, changing enum to union type, is no problem to the community and its users according to some issues.

relay-tools/relay-compiler-language-typescript#81
relay-tools/relay-compiler-language-typescript#164

And we can't change AuthType enum type in src/types/graphql.ts to union type either. Because AuthType enum is also generated by graphql-codegen library, and also it is widely used in the clilent side code like below and it seems irreplaceable.

// src/components/screen/Settings.tsx

  switch (user?.profile?.authType) {
    case AuthType.google:
      signInInfoOption = {
      ...
// src/components/screen/SignIn.tsx

<SocialSignInButton
  clientId={facebookAppId}
  clientSecret={facebookSecret}
  svgIcon={<SvgFacebook width={18} height={18} fill={theme.facebookIcon}/>}
  onUserCreated={(user?: User): void => {
    if (user) setUser(user);
  }}
  socialProvider={AuthType.facebook}
/>

...

So, in my opinion, we should deal with union Type AuthType in src/__generated__/AppUserQuery.graphql.ts to fix the compatibility issue.


Possible workarounds

1. Change union type AuthType to enum Type in src/__generated__/AppUserQuery.graphql.ts by a compiler or something else.

To be honest, I don't know how to do this.
And I'm not sure whether this change makes no side effect.


2. Current makeshift

Add // @ts-ignore ==> TODO


Related Issues

#147

@smallbee3 smallbee3 changed the title Union type generated by relay-compiler is not compatible with enum type generated by codegen. Union type generated by relay-compiler is not compatible with enum type generated by codegen Jul 2, 2020
@smallbee3 smallbee3 added client and removed bug labels Jul 2, 2020
hyochan added a commit that referenced this issue Jul 2, 2020
@smallbee3
Copy link
Contributor Author

Issue sovled by PR #151

hyochan added a commit that referenced this issue Jul 2, 2020
@hyochan hyochan closed this as completed Jul 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants