diff --git a/CHANGELOG.md b/CHANGELOG.md index c50ccc0dba..39a6166a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange ### Fixed * [`no-unused-state`]: avoid a crash on type-only gDSFP declarations ([#3225][] @ljharb) * [`jsx-curly-brace-presence`]: the string "never" defaults to `propElementValues` as `ignore` ([#3228][] @ljharb) +* [`propTypes`]: add `VFC` to react generic list ([#3230][] @ljharb) +[#3230]: https://github.com/yannickcr/eslint-plugin-react/issues/3230 [#3228]: https://github.com/yannickcr/eslint-plugin-react/issues/3228 [#3225]: https://github.com/yannickcr/eslint-plugin-react/issues/3225 diff --git a/lib/util/propTypes.js b/lib/util/propTypes.js index 8da9fb9f15..a61a57d67b 100644 --- a/lib/util/propTypes.js +++ b/lib/util/propTypes.js @@ -100,7 +100,7 @@ module.exports = function propTypesInstructions(context, components, utils) { const defaults = { customValidators: [] }; const configuration = Object.assign({}, defaults, context.options[0] || {}); const customValidators = configuration.customValidators; - const allowedGenericTypes = new Set(['forwardRef', 'ForwardRefRenderFunction', 'VoidFunctionComponent', 'PropsWithChildren', 'SFC', 'StatelessComponent', 'FunctionComponent', 'FC']); + const allowedGenericTypes = new Set(['forwardRef', 'ForwardRefRenderFunction', 'VFC', 'VoidFunctionComponent', 'PropsWithChildren', 'SFC', 'StatelessComponent', 'FunctionComponent', 'FC']); const genericTypeParamIndexWherePropsArePresent = { ForwardRefRenderFunction: 1, forwardRef: 1, diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js index b6f1e80a9a..d44285ab0f 100644 --- a/tests/lib/rules/prop-types.js +++ b/tests/lib/rules/prop-types.js @@ -7746,6 +7746,27 @@ ruleTester.run('prop-types', rule, { ], features: ['ts', 'no-babel'], }, + { + code: ` + import React, { VFC } from 'react' + + interface Props { + age: number + } + const Hello: VFC = function Hello(props) { + const { test } = props; + + return
Hello {name}
; + } + `, + errors: [ + { + messageId: 'missingPropType', + data: { name: 'test' }, + }, + ], + features: ['ts', 'no-babel'], + }, { code: ` import React from 'react' @@ -7771,6 +7792,27 @@ ruleTester.run('prop-types', rule, { code: ` import React from 'react' + interface Props { + age: number + } + const Hello: React.VFC = function Hello(props) { + const { test } = props; + + return
Hello {name}
; + } + `, + errors: [ + { + messageId: 'missingPropType', + data: { name: 'test' }, + }, + ], + features: ['ts', 'no-babel'], + }, + { + code: ` + import React from 'react' + type IfooProps = { e: string }; const Foo: React.ForwardRefRenderFunction = function Foo (props, ref) { const { name } = props; @@ -7971,6 +8013,25 @@ ruleTester.run('prop-types', rule, { ], features: ['ts', 'no-babel'], }, + { + code: ` + import React from 'react'; + + export interface PersonProps { + username: string; + } + const Person: React.VFC = (props): React.ReactElement => ( +
{props.nonExistent}
+ ); + `, + errors: [ + { + messageId: 'missingPropType', + data: { name: 'nonExistent' }, + }, + ], + features: ['ts', 'no-babel'], + }, { code: ` const Foo = ({ foo }) => {