Search code examples
reactjstypescriptreact-nativeeslinttsdoc

tsdoc-param-tag-with-invalid-name: The @param block should be followed by a valid parameter name (TypeScript ESLint and React)


I'm using JSDoc and TSDoc for a React Native project with TypeScript. There is some strange behavior when documentings props.

All @param: props.propName are underlined with message:

tsdoc-param-tag-with-invalid-name: The @param block should be followed by a valid parameter name: The identifier cannot non-word characterseslinttsdoc/syntax

Also, I'm obliged to add : Props twice because if I only put it in FC the props are underlined with:

'onPress' is missing in props validationeslintreact/prop-types

The code:

import React, { useContext, FC } from 'react'
import { GestureResponderEvent, ViewStyle } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import { UserAvatarContext } from '../apps'
import Avatar from './Avatar'

interface Props {
  size?: number
  radius?: number
  style?: ViewStyle
  onPress?: (event: GestureResponderEvent) => void
}

/**
 * Display the user profile avatar and link
 *
 * @param props - React props
 * @param props.size - the size of the avatar in pixels
 * @param props.radius - the border radius in pixels
 * @param props.onPress - the function to use when pressing the avatar (by default, navigate to the user profile page)
 * @param props.style - Additional style information
 * @returns The avatar icon
 */
const UserAvatar: FC<Props> = ({ size = 40, radius, style, onPress }: Props) => {
  const navigation = useNavigation()
  const { source } = useContext(UserAvatarContext)
  const defaultOnPress = (): void => navigation.navigate('My profile')

  return <Avatar source={source} onPress={onPress || defaultOnPress} size={size} style={style} radius={radius} />
}

export default UserAvatar

I'd like it to be clean, yet I feel I need to make some configurations or modify the way of declaring my props. Any idea?

Thanks


Solution

  • Just move the property description to the interface definition, like on below:

    import React, { useContext, FC } from 'react'
    import { GestureResponderEvent, ViewStyle } from 'react-native'
    import { useNavigation } from '@react-navigation/native'
    import { UserAvatarContext } from '../apps'
    import Avatar from './Avatar'
    
    interface Props {
      // the size of the avatar in pixels
      size?: number
      // the border radius in pixels
      radius?: number
      // Additional style information
      style?: ViewStyle
      // the function to use when pressing the avatar (by default, navigate to the user profile page)
      onPress?: (event: GestureResponderEvent) => void
    }
    
    /**
     * Display the user profile avatar and link
     *
     * @param props - React props
     */
    const UserAvatar: FC<Props> = ({ size = 40, radius, style, onPress }: Props) => {
      const navigation = useNavigation()
      const { source } = useContext(UserAvatarContext)
      const defaultOnPress = (): void => navigation.navigate('My profile')
    
      return <Avatar source={source} onPress={onPress || defaultOnPress} size={size} style={style} radius={radius} />
    }