Skip to content

Instantly share code, notes, and snippets.

@gaving
Created August 26, 2025 17:17
Show Gist options
  • Save gaving/31416d34e427f86526001912912bea0c to your computer and use it in GitHub Desktop.
Save gaving/31416d34e427f86526001912912bea0c to your computer and use it in GitHub Desktop.
A codemod that adds missing generic <any> types to untyped Apollo hooks
// Patch ANY untyped Apollo-ish hooks: useQuery/useLazyQuery (<any>), useMutation (<any, any>)
// regardless of import origin (direct, re-exports, namespace, etc.)
module.exports.parser = "tsx";
module.exports = function transformer(file, api) {
const j = api.jscodeshift;
const root = j(file.source);
const HOOKS = {
useQuery: { arity: 1 },
useLazyQuery: { arity: 1 },
useMutation: { arity: 2 },
};
function isAlreadyTyped(call) {
if (call.typeArguments) return true; // e.g., useQuery<Foo>(...)
const firstArg = call.arguments && call.arguments[0];
if (!firstArg) return false;
// If the first arg is already cast (as TypedDocumentNode<...>) or any TS assertion, skip
if (firstArg.type === "TSAsExpression" || firstArg.type === "TypeAssertion")
return true;
return false;
}
function hookKind(call) {
const callee = call.callee;
// Identifier form: useQuery(...)
if (callee.type === "Identifier" && HOOKS[callee.name]) {
return callee.name;
}
// Member form: Apollo.useQuery(...), MyApollo.useMutation(...), etc.
if (
callee.type === "MemberExpression" &&
callee.property.type === "Identifier" &&
HOOKS[callee.property.name]
) {
return callee.property.name;
}
return null;
}
function addTypeArgs(call, n) {
const anyT = j.tsAnyKeyword();
call.typeArguments = j.tsTypeParameterInstantiation(
Array.from({ length: n }, () => anyT),
);
}
root.find(j.CallExpression).forEach((path) => {
const node = path.value;
const kind = hookKind(node);
if (!kind) return; // not a hook we care about
if (isAlreadyTyped(node)) return; // skip already-typed/casted
addTypeArgs(node, HOOKS[kind].arity);
});
return root.toSource({ quote: "single", trailingComma: true });
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment