graphql-typed-document-node
graphql-typed-document-node copied to clipboard
fix: update variable type variance to bivariant
Summary
I've updated the implementation of the __apiType method to shorthand method definition. This modification enables bivariance in the variable type.
Details
Let's consider a function that takes a specific TypedDocumentNode with certain requirements. Assume this function, queryAnimal, receives a Graphql query with AnimalQueryResult as the return type and AnimalQueryVariable as the argument type.
Suppose dogDocumentNode has a narrower scope than AnimalQueryResult for the Return Type ({ name: string; id: string; age: number }) and a narrower scope than AnimalQueryVariable for the Variable Type ({ id: string }). As a result, it should be usable as an argument for queryAnimal. However, due to the Variable Type of TypedDocumentNode being a function argument, TypeScript conducts type checking contravariantly for the VariableType, making it ineligible as an argument.
To create a bivariant function argument in TypeScript, the method needs to be defined as a Shorthand Definition.
type ResultOf<T> = T extends TypedDocumentNode<infer R, any> ? R : never;
type VariablesOf<T> = T extends TypedDocumentNode<any, infer V> ? V : never;
// type TypedDocumentNode<R, V> = { __apiType?: (variables: V) => R }; // AS-IS
type TypedDocumentNode<R, V> = { __apiType?(variables: V): R }; // TO-BE
type AnimalQueryResult = Record<
string,
{ name: string; id: string; age: number; [key: string]: any }
>;
type AnimalQueryVariable = Record<string, any>;
function queryAnimal<
DN extends TypedDocumentNode<R, V>,
R extends AnimalQueryResult,
V extends AnimalQueryVariable
>(query: DN, variable: VariablesOf<DN>): ResultOf<DN> {
return "" as any;
}
const dogDocumentNode = "" as TypedDocumentNode<
{ dogQuery: { name: string; id: string; age: number } },
{ id: string }
>;
const dog = queryAnimal(dogDocumentNode, { id: "5172" });
const catDocumentNode = "" as TypedDocumentNode<
{ catQuery: { name: string; id: string } },
{ id: string }
>;
const cat = queryAnimal(catDocumentNode, { id: "5713" });
References
TypeScript FAQ: Why are function parameters bivariant? Typescript Repo: Strict function types #18654
⚠️ No Changeset found
Latest commit: ab9e8c3eaa0b7b1ef258c50563877662ad184445
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR