From da1cc91e9527d7d02cf3532c8cf13293a9cc6723 Mon Sep 17 00:00:00 2001 From: Akul Srivastava Date: Wed, 9 Aug 2023 14:26:50 +0530 Subject: [PATCH] [New] `sort-prop-types`: give errors on TS types --- CHANGELOG.md | 4 ++ lib/rules/sort-prop-types.js | 40 ++++++++++++++ tests/lib/rules/sort-prop-types.js | 87 +++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c56e0b16d1..90111929e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,13 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange ## Unreleased +### Added +* [`sort-prop-types`]: give errors on TS types ([#3615][] @akulsr0) + ### Fixed * [`no-deprecated`]: prevent false positive on commonjs import ([#3614][] @akulsr0) +[#3615]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3615 [#3614]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3614 ## [7.33.1] - 2023.07.29 diff --git a/lib/rules/sort-prop-types.js b/lib/rules/sort-prop-types.js index 56e67033c7..98878c47a0 100644 --- a/lib/rules/sort-prop-types.js +++ b/lib/rules/sort-prop-types.js @@ -65,6 +65,8 @@ module.exports = { const noSortAlphabetically = configuration.noSortAlphabetically || false; const sortShapeProp = configuration.sortShapeProp || false; + const typeAnnotations = new Map(); + function getKey(node) { if (node.key && node.key.value) { return node.key.value; @@ -215,6 +217,21 @@ module.exports = { } } + function handleFunctionComponent(node) { + const firstArg = node.params[0].typeAnnotation && node.params[0].typeAnnotation.typeAnnotation; + if (firstArg && firstArg.type === 'TSTypeReference') { + const propType = typeAnnotations.get(firstArg.typeName.name) + && typeAnnotations.get(firstArg.typeName.name)[0]; + if (propType && propType.members) { + checkSorted(propType.members); + } + } else if (firstArg && firstArg.type === 'TSTypeLiteral') { + if (firstArg.members) { + checkSorted(firstArg.members); + } + } + } + return { CallExpression(node) { if (!sortShapeProp || !isShapeProp(node) || !(node.arguments && node.arguments[0])) { @@ -261,6 +278,29 @@ module.exports = { } }); }, + + TSTypeLiteral(node) { + if (node && node.parent.id) { + const currentNode = [].concat( + typeAnnotations.get(node.parent.id.name) || [], + node + ); + typeAnnotations.set(node.parent.id.name, currentNode); + } + }, + + TSTypeAliasDeclaration(node) { + if (node.typeAnnotation.type === 'TSTypeLiteral' || node.typeAnnotation.type === 'ObjectTypeAnnotation') { + const currentNode = [].concat( + typeAnnotations.get(node.id.name) || [], + node.typeAnnotation + ); + typeAnnotations.set(node.id.name, currentNode); + } + }, + + FunctionDeclaration: handleFunctionComponent, + ArrowFunctionExpression: handleFunctionComponent, }; }, }; diff --git a/tests/lib/rules/sort-prop-types.js b/tests/lib/rules/sort-prop-types.js index d7417c005a..bfb9197529 100644 --- a/tests/lib/rules/sort-prop-types.js +++ b/tests/lib/rules/sort-prop-types.js @@ -2250,6 +2250,91 @@ ruleTester.run('sort-prop-types', rule, { line: 4, }, ], - } : [] + } : [], + { + code: ` + type Props = { + zzz: string; + aaa: string; + } + function Foo(props: Props) { + return null; + } + `, + output: ` + type Props = { + aaa: string; + zzz: string; + } + function Foo(props: Props) { + return null; + } + `, + features: ['ts', 'no-babel'], + errors: [ + { + messageId: 'propsNotSorted', + line: 4, + column: 11, + type: 'TSPropertySignature', + }, + ], + }, + { + code: ` + type Props = { + zzz: string; + aaa: string; + } + const Foo = (props: Props) => { + return null; + } + `, + output: ` + type Props = { + aaa: string; + zzz: string; + } + const Foo = (props: Props) => { + return null; + } + `, + features: ['ts', 'no-babel'], + errors: [ + { + messageId: 'propsNotSorted', + line: 4, + column: 11, + type: 'TSPropertySignature', + }, + ], + }, + { + code: ` + const Foo = (props: { + zzz: string, + aaa: string, + }) => { + return null; + } + `, + output: ` + const Foo = (props: { + aaa: string, + zzz: string, + }) => { + return null; + } + `, + features: ['ts', 'no-babel'], + errors: [ + { + messageId: 'propsNotSorted', + line: 4, + column: 11, + type: 'TSPropertySignature', + }, + ], + } )), });