Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript "'className' is missing in props validation" despite being defined #3284

Closed
awwong1 opened this issue May 8, 2022 · 11 comments · Fixed by #3749
Closed

Typescript "'className' is missing in props validation" despite being defined #3284

awwong1 opened this issue May 8, 2022 · 11 comments · Fixed by #3749

Comments

@awwong1
Copy link

awwong1 commented May 8, 2022

Description

I am observing 'className' is missing in props validation despite it being correctly specified in the type definition.

Versions

    "@types/react": "^18.0.0",
    "eslint": "^8.8.0",
    "eslint-plugin-react": "^7.28.0",
    "react": "^18.0.0",
    "typescript": "^4.5.5"

Example

import React from 'react'

const classNames = (...classes: (false | null | undefined | string)[]) =>
  classes.filter(Boolean).join(' ')


export const Input = (
  props: React.DetailedHTMLProps<
    React.InputHTMLAttributes<HTMLInputElement>,
    HTMLInputElement
  >
) => (
  <input
    {...props}
    className={classNames(
      'class-a',
      'class-b',
      // eslint-disable-next-line react/prop-types
      props.className
    )}
  />
)

Expected behaviour

The eslint-disable-next-line should not be necessary.
I can also workaround this by adding in & { className?: string } into the type definition of props.

  props: React.DetailedHTMLProps<
    React.InputHTMLAttributes<HTMLInputElement>,
    HTMLInputElement
  > & { className?: string }
@ljharb
Copy link
Member

ljharb commented May 8, 2022

Seems like React.DetailedHTMLProps is a thing we don't have any knowledge of, and we'd have to hardcode support for (probably React.InputHTMLAttributes as well).

@lokve
Copy link

lokve commented May 23, 2022

I have the same problem

type TDelIconProps = React.HTMLProps<HTMLDivElement>;

const DelIcon: React.FC<TDelIconProps> = ({className, ...rest}) => (
    <div className={classNames('del flex-center', className)} {...rest}>
        <i className="iconfont icon-del f12" />
    </div>
);

ESLint: 'className' is missing in props validation(react/prop-types)

Versions

eslint:7.32.0
eslint-plugin-react:7.30.0

@DerPipo
Copy link

DerPipo commented Dec 5, 2022

It seems weird to me, but this workaround, using an interface and extending DetailedHTMLAttributes, seems to work:

interface InputProps  extends React.DetailedHTMLProps<
  React.InputHTMLAttributes<HTMLInputElement>,  
  HTMLInputElement
> {}

export const Input = (
  props: InputProps
) => (
  // your code
);

@rwb196884
Copy link

Still broken in 7.33.2

@ljharb
Copy link
Member

ljharb commented Nov 8, 2023

@rwb196884 its not broken, it’s just not something we support yet.

@divmgl
Copy link

divmgl commented Mar 27, 2024

If you import directly from React the error message goes away.

Works:

import type { HTMLAttributes } from "react"
import { cn } from "../../lib/utils"

export function Heading({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("font-semibold text-lg", className)} {...props} />
}

Does not work:

import React from "react"
import { cn } from "../../lib/utils"

export function Heading({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("font-semibold text-lg", className)} {...props} />
}

ojeytonwilliams added a commit to Sembauke/ui that referenced this issue Apr 8, 2024
Our prop types are fine, but eslint-react isn't detecting them
correctly.

With a little help

jsx-eslint/eslint-plugin-react#3284 (comment)

we can tell it what the props are.
@fernandocanizo
Copy link

@divmgl I found the same issue and workaround but I'm completely puzzled about why does that behave that way. Isn't it supposed to import the exact same thing? If you (or anyone) know/s the reason this import behaves like this, I'd like to learn why. Cause right now, seeing this, to me Javascript became broken.

What I'm missing? Do they import different things just because the same thing is imported in different ways?

To be completely clear, I'm referring to this:

import type { HTMLAttributes } from "react"
// ...
export function Heading({ className, ...props }: HTMLAttributes<HTMLDivElement>) {

versus this:

import React from "react"
// ...
export function Heading({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {

@divmgl
Copy link

divmgl commented May 15, 2024

I agree that this is a bug; I merely posted the workaround.

@sayjeyhi
Copy link

I have this issue with shadci generated components , like here:

const TabsList = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.List>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
  <TabsPrimitive.List
    ref={ref}
    className={cn(
      'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
      className,
    )}
    {...props}
  />
));

gives: ESLint: 'className' is missing in props validation(react/prop-types)

@KirillTregubov
Copy link

Still happens with Alert Dialog on the latest version (7.34.4).

const AlertDialogOverlay = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
>(({ className, ...props }, ref) => ( // 'className' is missing in props validation eslint[react/prop-types]
  <AlertDialogPrimitive.Overlay
    {...props}
    ref={ref}
  />
))

@ljharb
Copy link
Member

ljharb commented Jul 15, 2024

@KirillTregubov if AlertDialogPrimitive isn't defined in that file, then there's no practical way for eslint to know that className is defined in it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

9 participants