Expose `NodeTypes` from the GitHub plugin (#96)
Summary: This is useful for metaprogramming. For instance, suppose we have an object like this: ```js const stringifiers = { ISSUE: (stringifyIssue: (Node<IssueNodePayload>) => string), COMMENT: (stringifyComment: (Node<CommentPayload>) => string), ... } ``` How do we type this? We might try ```js {[type: NodeType]: (Node<NodePayload>) => string} ``` but this is not correct, because `Node<IssueNodePayload>` is a subtype of `Node<NodePayload>`, and `(_) => K` is contravariant, not covariant. (In other words, a function from `Node<IssueNodePayload>` is not as general as a function from `Node<NodePayload>`.) We need to express a dependency between the object key and the value. We instead write: ```js type TypedNodeToStringifier = <T: $Values<NodeTypes>>( T ) => (node: Node<$ElementType<T, "payload">>) => string; (stringifiers: $Exact<$ObjMap<NodeTypes, TypedNodeToStringifier>>); ``` This expresses exactly (heh) the right type. Test Plan: Note that removing any of the elements of `NodeTypes` yields a Flow error, due to the static assertion following the type definition. wchargin-branch: node-types
This commit is contained in:
parent
559ed393a9
commit
e9ca833448
|
@ -109,6 +109,61 @@ export type NodeID =
|
|||
| AuthorNodeID;
|
||||
export type NodeType = $ElementType<NodeID, "type">;
|
||||
|
||||
// A map from NodeType string to the corresponding ID and payload types.
|
||||
// Primarily useful for adding static assertions with $ObjMap, but also
|
||||
// useful at the value layer as $ElementType<NodeTypes, "ISSUE">, for
|
||||
// instance.
|
||||
export type NodeTypes = {|
|
||||
ISSUE: {
|
||||
id: IssueNodeID,
|
||||
payload: IssueNodePayload,
|
||||
},
|
||||
PULL_REQUEST: {
|
||||
id: PullRequestNodeID,
|
||||
payload: PullRequestNodePayload,
|
||||
},
|
||||
COMMENT: {
|
||||
id: CommentNodeID,
|
||||
payload: CommentNodePayload,
|
||||
},
|
||||
PULL_REQUEST_REVIEW_COMMENT: {
|
||||
id: PullRequestReviewCommentNodeID,
|
||||
payload: PullRequestReviewCommentNodePayload,
|
||||
},
|
||||
PULL_REQUEST_REVIEW: {
|
||||
id: PullRequestReviewNodeID,
|
||||
payload: PullRequestReviewNodePayload,
|
||||
},
|
||||
USER: {
|
||||
id: UserNodeID,
|
||||
payload: UserNodePayload,
|
||||
},
|
||||
ORGANIZATION: {
|
||||
id: OrganizationNodeID,
|
||||
payload: OrganizationNodePayload,
|
||||
},
|
||||
BOT: {
|
||||
id: BotNodeID,
|
||||
payload: BotNodePayload,
|
||||
},
|
||||
|};
|
||||
(function staticAssertions() {
|
||||
// Check that node payload types are exhaustive.
|
||||
(x: NodeType): $Keys<NodeTypes> => x;
|
||||
|
||||
// Check that each type is associated with the correct ID type.
|
||||
// Doesn't work because of a Flow bug; should work if that bug is
|
||||
// fixed: https://github.com/facebook/flow/issues/4211
|
||||
// (Summary of bug: $ElementType<O, -> does not preserve unions.)
|
||||
//
|
||||
// <T: $Keys<NodeTypes>>(
|
||||
// x: T
|
||||
// ): $ElementType<
|
||||
// $ElementType<$ElementType<NodeTypes, T>, "id">,
|
||||
// "type"
|
||||
// > => x;
|
||||
});
|
||||
|
||||
export type AuthorshipEdgePayload = {};
|
||||
export type AuthorshipEdgeID = {
|
||||
+type: "AUTHORSHIP",
|
||||
|
|
Loading…
Reference in New Issue