UNPKG

@patrickemoore/eslint-plugin-aliased-props

Version:

An ESLint plugin to enforce aliased (named) types for React component props.

110 lines (93 loc) 2.58 kB
/** * @fileoverview Require React component props to have an aliased (named) type. */ 'use strict'; module.exports = { meta: { type: 'suggestion', docs: { description: 'Require React component props to have an aliased (named) type.', category: 'Best Practices', recommended: false, }, fixable: null, // or 'code' if you implement autofix schema: [], // No options }, create(context) { const ts = require('@typescript-eslint/typescript-estree'); return { FunctionDeclaration(node) { checkPropsParameter(node); }, ArrowFunctionExpression(node) { if ( node.parent && node.parent.type === 'VariableDeclarator' ) { checkPropsParameter(node); } else if ( node.parent && node.parent.type === 'CallExpression' ) { checkPropsParameter(node); } }, FunctionExpression(node) { checkPropsParameter(node); } }; function checkPropsParameter(node) { const isReactComponent = isNodeReactComponent(node); if (!isReactComponent) { return; } const firstParam = node.params[0]; if ( !firstParam || (firstParam.type !== 'Identifier' && firstParam.type !== 'ObjectPattern') ) { return; } const typeAnnotation = firstParam.typeAnnotation; if ( typeAnnotation && typeAnnotation.typeAnnotation && typeAnnotation.typeAnnotation.type === 'TSTypeLiteral' ) { context.report({ node: typeAnnotation, message: 'Props should use a named interface or type alias instead of an inline type.', }); } } function isNodeReactComponent(node) { // Check if the function returns JSX let hasJSX = false; const sourceCode = context.getSourceCode(); const visitorKeys = sourceCode.visitorKeys; function traverse(node) { if (node.type === 'JSXElement' || node.type === 'JSXFragment') { hasJSX = true; return; } const keys = visitorKeys[node.type]; if (!keys) { return; } for (const key of keys) { const child = node[key]; if (Array.isArray(child)) { for (const c of child) { traverse(c); } } else if (child) { traverse(child); } } } traverse(node.body); return hasJSX; } }, };