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

Distinguish union type via __typename in subscription updater function #186

Open
n1ru4l opened this issue May 18, 2020 · 1 comment
Open

Comments

@n1ru4l
Copy link
Member

n1ru4l commented May 18, 2020

Schema:

type User {
  id: ID!
  name: String!
}

type UserAddUpdate {
  user: User!
}

type UserRemoveUpdate {
  userId: ID!
}

union UserUpdateSubscription = UserAddUpdate | UserRemoveUpdate

type Subscription {
  userUpdate: UserUpdateSubscription!
}

Subscription:

React.useEffect(() => {
    const subscription = requestSubscription<chatUserUpdateSubscription>(
      environment,
      {
        subscription: UserUpdateSubscription,
        variables: {},
        updater: (store) => {
          const users = ConnectionHandler.getConnection(
            store.getRoot(),
            "chat_users"
          );

          const updateRecord = store.getRootField("userUpdate");

          if (!users || !updateRecord) return;

          if (updateRecord.getValue("__typename") === "UserAddUpdate") {
            const edge = ConnectionHandler.createEdge(
              store,
              users,
              updateRecord.getLinkedRecord("user"),
              "User"
            );
            ConnectionHandler.insertEdgeAfter(users, edge);
          } else if (
            updateRecord.getValue("__typename") === "UserRemoveUpdate"
          ) {
            // updateRecord should be
            // RecordProxy<{
            //   readonly __typename: "UserRemoveUpdate";
            //   readonly userId: string;
            // }
            // userId should be a string
            const userId = updateRecord.getValue("userId");
            if (typeof userId !== "string") return;
            ConnectionHandler.deleteNode(users, userId);
          }
        },
      }
    );
    return () => subscription.dispose();
  }, [environment]);

Maybe it is possible to correctly infer the type based on the __typename property comparison?

@n1ru4l n1ru4l changed the title Distinguish union type via _typename in subscription updater function Distinguish union type via __typename in subscription updater function May 18, 2020
@n1ru4l
Copy link
Member Author

n1ru4l commented May 28, 2020

I came up with the following helper function:

export const isAbstractGraphQLMemberType = <
  T extends { readonly __typename: string },
  A extends Exclude<T["__typename"], "%other">
>(
  input: RecordProxy<T>,
  expectedType: A
): input is RecordProxy<Extract<T, { readonly __typename: A }>> => {
  return input.getValue("__typename") === expectedType;
};

Usage Example:

if (isAbstractGraphQLMemberType(updateRecord, "UserAddUpdate")) {
  const edge = ConnectionHandler.createEdge(
    store,
    users,
    updateRecord.getLinkedRecord("user"),
    "User"
  );
  ConnectionHandler.insertEdgeAfter(users, edge);
} else if (isAbstractGraphQLMemberType(updateRecord, "UserRemoveUpdate")) {
  const userId = updateRecord.getValue("userId");
  ConnectionHandler.deleteNode(users, userId);
}

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

1 participant