UNPKG

eslint-plugin-no-usememo-generics

Version:

A custom ESLint plugin to prevent generics in useMemo function calls.

115 lines (103 loc) 3.7 kB
const meta = { type: "problem", docs: { description: "Prevent providing generics in useMemo calls.", }, fixable: "code", hasSuggestions: true, messages: { moveGenericToReturnType: "Move the generic of useMemo to the return type of the factory function.", removeGeneric: "Remove generic from useMemo.", }, schema: [], }; function create(context) { return { // Performs action in the function on every variable declarator VariableDeclarator(node) { // Check if the node is a `const` variable declaration if (node.parent.kind !== "const") return; // Check if we're calling useMemo to initialize the variable if ( node.init && node.init.type === "CallExpression" && node.init.callee && node.init.callee.name === "useMemo" ) { // Check if we're providing a generic to useMemo if ( node.init.typeArguments && node.init.typeArguments.params.length > 0 ) { // Check if the first argument is a function if ( node.init.arguments && node.init.arguments[0] && ["ArrowFunctionExpression", "FunctionExpression"].includes( node.init.arguments[0].type, ) ) { // If the function doesn't have a return type, move the generic from useMemo to the return type of the factory function if (!node.init.arguments[0].returnType) { const functionNode = node.init.arguments[0]; const returnTypePosition = getReturnTypePosition( context.sourceCode.getText(functionNode), ); context.report({ node, messageId: "moveGenericToReturnType", fix(fixer) { const fixes = [ // Remove the generic type from useMemo fixer.remove(node.init.typeArguments), ]; if (returnTypePosition !== -1) { // Replace the generic type in the function return type fixes.push( fixer.insertTextAfterRange( [ functionNode.range[0], functionNode.range[0] + returnTypePosition, ], ": " + context.sourceCode.getText( node.init.typeArguments.params[0], ), ), ); } return fixes; }, }); } else { // If the factory function of useMemo already has a return type, just remove the generic from useMemo context.report({ node, messageId: "removeGeneric", fix(fixer) { return fixer.remove(node.init.typeArguments); }, }); } } } } }, }; } export default { meta, create }; /** * Helper function to get the position of the return type in a function string * @param {string} functionString * @returns {number} the position of the return type in the function string, or -1 if it couldn't be found */ const getReturnTypePosition = (functionString) => { // Matches the function signature (function or arrow) without any arguments since useMemo only accepts functions without arguments const regex = /(function)?\s*\(\s*\)/; const match = functionString.match(regex); if (match) { return match[0].length; } return -1; };