ui icon indicating copy to clipboard operation
ui copied to clipboard

Is typescript-eslint not compatible?

Open renja-g opened this issue 2 years ago • 4 comments

I'm using typescript-eslint in my project, and I noticed that most or all components are giving errors.

Example:

// input.tsx
import * as React from 'react';

import { cn } from '~/lib/utils';

export interface InputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, ...props }, ref) => {
    return (
      <input
        className={cn(
          'flex h-10 w-full rounded-md border border-slate-300 bg-transparent px-3 py-2 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900',
          className
        )}
        ref={ref}
        {...props}
      />
    );
  }
);
Input.displayName = 'Input';

export { Input };

Is giving an error at:

export interface InputProps
                 ^^^^^^^^^^
An interface declaring no members is equivalent to its supertype.eslint[@typescript-eslint/no-empty-interface](https://typescript-eslint.io/rules/no-empty-interface)

So my questing is if it is intentional or knows that shadcn/ui is not compatible with typescript-eslint which is standard for Create T3 App

renja-g avatar Apr 14 '23 10:04 renja-g

I fixes this in the latest release. Will push the fix soon.

Thanks for the heads up.

shadcn avatar Apr 14 '23 10:04 shadcn

Good to hear, can I already find the changes somewhere in the repo?

renja-g avatar Apr 14 '23 11:04 renja-g

Of course.

  1. Install @typescript-eslint/parser.

  2. Add the following to your .eslintrc.json file.

+ "overrides": [
+    {
+     "files": ["*.ts", "*.tsx"],
+     "parser": "@typescript-eslint/parser"
+   }
+ ]
  1. Run npm lint --fix

shadcn avatar Apr 14 '23 11:04 shadcn

Ahh, thank you very much. btw. this is a really cool project, keep going!

renja-g avatar Apr 14 '23 11:04 renja-g

Had a look into this, I think the way it's written in the shadcn components is a good way of doing it. By default there's no extension, but you can add more parameters to extend the component when you need to.

(this is a contrived example. I would use CVA to do something like this in ernest)

export interface InputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {
  foo?: boolean
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, type, foo = false, ...props }, ref) => {
    return (
      <input
        type={type}
        className={cn(
          'flex h-10 w-full rounded-md border-hidden border-input bg-card px-3 py-2 text-sm shadow-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50',
          className,
          foo && 'bg-red-500',
        )}
        ref={ref}
        {...props}
      />
    )
  },
)
Input.displayName = 'Input'

export { Input }

If you do the autofix, you end up with a straight assignment, which means you have to revert the change to end up adding back types.

// how do I add foo here?
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>

Instead I can modify the @typescript-eslint/no-empty-interface rule with allowSingleExtends to not bother me if I have an empty interface as used in the shadcn components

This is the current t3 config with the extra rule modification added. Might be worth seeing if the t3 crew are interested in adding this as a default considering that the ShadCN / T3 combo is pretty common, or might be something that the shadcn CLI could do during the init/install process.

const config = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: true,
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'next/core-web-vitals',
    'plugin:@typescript-eslint/recommended-type-checked',
    'plugin:@typescript-eslint/stylistic-type-checked',
  ],
  rules: {
    // These opinionated rules are enabled in stylistic-type-checked above.
    // Feel free to reconfigure them to your own preference.
    '@typescript-eslint/array-type': 'off',
    '@typescript-eslint/consistent-type-definitions': 'off',

    '@typescript-eslint/consistent-type-imports': [
      'warn',
      {
        prefer: 'type-imports',
        fixStyle: 'inline-type-imports',
      },
    ],
    '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
    // added this rule modification
    '@typescript-eslint/no-empty-interface': [
      'error',
      { allowSingleExtends: true },
    ],
  },
}

AndKenneth avatar Aug 03 '23 01:08 AndKenneth

Pls. fix I also have the error today.

FleetAdmiralJakob avatar Sep 05 '23 14:09 FleetAdmiralJakob

@FleetAdmiralJakob does adding the no-empty-interface rule modification as above (with allowSingleExtends: true) work for you?

AndKenneth avatar Sep 11 '23 22:09 AndKenneth

It works, but I think I can't live with that as a permanent solution that every time I want to work with T3 and shadcn/ui I have to change this

FleetAdmiralJakob avatar Sep 12 '23 14:09 FleetAdmiralJakob

I would create a PR if @shadcn would merge another solution

FleetAdmiralJakob avatar Sep 12 '23 14:09 FleetAdmiralJakob

Quite simply this is not a shadcn issue. Your linter is complaining about something that's not a bug. It's a stylistic choice. Make the PR in the T3 project, not here. I was thinking about doing it, but haven't gotten around to it.

AndKenneth avatar Sep 13 '23 08:09 AndKenneth

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jul 09 '24 23:07 shadcn