16

I am getting an ESlint error Don't use `{}` as a type. `{}` actually means "any non-nullish value". in my Contact component whiling using React and TypeScript.

The component doesn't have any props.

export default class Contact extends React.Component<{}, MyState> {
    constructor(props = {}) {
        super(props);
        this.state = {
            signedUp: false,
        };
    }
}

I tried using null instead, but that threw other ESLint errors.

2
  • Would unknown do? Or may be even never Commented Mar 24, 2021 at 2:36
  • I did not try never, but unknown created issues of it's own. Commented Mar 25, 2021 at 3:50

3 Answers 3

30

After a lot of digging I found the following GitHub issues.

By adding the following to your .eslintrc.js you are able to ignore the rule. It is recommended to use Configurations to have this rule only apply to React components. This will ensure strong typing everywhere else.

  "rules": {
    "@typescript-eslint/ban-types": [
      "error",
      {
        "extendDefaults": true,
        "types": {
          "{}": false
        }
      }
    ]
  }
}

Source: https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492

Sign up to request clarification or add additional context in comments.

1 Comment

Excerpt from the link above: If you are using React, and you want to define type Props = {}. This is technically safe in this instance, because under the hood the {} type is passed into an intersection type (see the note at the end of this comment for why this is safe). explains why this is safe to do in react. I'm not sure you want to turn this off everywhere. @Iboyel answer seems more accurate.
16

I strongly disagree that the chosen answer is correct. This warning exists for a reason; for anyone Googling it, I'll leave it as what ESLint says:

  • If you want a type meaning "any object", you probably want Record<string, unknown> instead.
  • If you want a type meaning "any value", you probably want unknown instead.
  • If you want a type meaning "empty object", you probably want Record<string, never> instead.

1 Comment

The problem is with the ergonomics. Adding props to the empty object should be as natural as adding props. "Record<string, never>" fails this flow because you have to delete it first. Not to mention the unintuitive notion of it.
9

Expanding on Jordan answer to apply this rule to only React components in the .eslintrc.js file add

overrides: [
    {
        // Apply rule override only to files with the following extensions
        files: ['*.tsx', '*.jsx'],
        rules: {
            '@typescript-eslint/ban-types': [
                'error',
                {
                    extendDefaults: true,
                    types: {
                        '{}': false,
                    },
                },
            ],
        },
    },
]

4 Comments

Wouldn't {[k: string | number | symbol]: never} work in place of {} ?
It doesn't seem to be complete code, right?
I'd argue that Middlewares would normally live in ts files. So ['*.ts', '*.tsx'] seems more correct to me.
Very good addition, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.