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

Re-enable @typescript-eslint/consistent-type-definitions #1933

Merged
merged 4 commits into from
Nov 7, 2023

Conversation

mcmire
Copy link
Contributor

@mcmire mcmire commented Oct 25, 2023

Explanation

This ESLint rule was disabled in a previous commit when our ESLint config packages were bumped, because it caused lint violations.

This commit re-enables this rule going forward. However, since fixing the lint violations by converting interfaces to types would cause breaking changes, this commit adds inline overrides to allow existing interfaces to exist.

References

Fixes #1932.

Changelog

(No consumer-facing changes.

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@mcmire mcmire requested a review from a team as a code owner October 25, 2023 22:32
@legobeat
Copy link
Contributor

(No consumer-facing changes.

With regards to types, this is actually a breaking change (1, 2)

Some options:

  1. Invert the rule here (enforce consistent interface rather than type)
  2. Add eslint-disable exceptions explicitly for existing exported types
  3. Make it a breaking change

@mcmire
Copy link
Contributor Author

mcmire commented Oct 27, 2023

Ah, you are right. Hmm. This makes me wonder why we chose to enforce type aliases instead of interfaces again. I will think about this.

@mcmire
Copy link
Contributor Author

mcmire commented Oct 27, 2023

This is the commit in eslint-config when we enforced type aliases instead of interfaces: MetaMask/eslint-config#216. There is a thread in chat which also talks about this (this might get eaten by the data retention gods eventually, but for now search for "TypeScript interfaces", then find a message by Erik on November 29, 2021). Apparently interfaces caused frustration because they prevented the Json type from being used effectively. I wonder whether the problem in question could have been solved a different way however.

@MajorLift

This comment was marked as outdated.

MajorLift
MajorLift previously approved these changes Oct 27, 2023
@mcmire mcmire requested a review from a team as a code owner November 2, 2023 19:03
Convert all uses of `interface` to `type`, taking care to reverse cases
in which interfaces are extending other interfaces (`A extends B` should
come out to `B & A`).
@mcmire mcmire force-pushed the reenable-consistent-type-definitions branch from b344fc6 to 06db854 Compare November 2, 2023 19:06
@mcmire
Copy link
Contributor Author

mcmire commented Nov 2, 2023

I rebased this branch, as the history somehow got corrupted after merging main. Now everything is in one commit.

I've addressed the existing violations by adding inline overrides instead of converting them to type (except in test files).

Ready for another review.

@mcmire
Copy link
Contributor Author

mcmire commented Nov 7, 2023

Fixed merge conflicts.

Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@mcmire mcmire merged commit c864e48 into main Nov 7, 2023
@mcmire mcmire deleted the reenable-consistent-type-definitions branch November 7, 2023 20:33
MajorLift added a commit to MetaMask/metamask-extension that referenced this pull request Mar 14, 2024
…eslint/consistent-type-definitions` rule (#23439)

## **Description**

### Motivation

`interface` usage is banned in MetaMask codebases. With TypeScript
conversion efforts in progress, it's time to enforce `type` usage over
`interface` in the extension codebase as well, especially for new
contributions in TypeScript.

There are a few reasons for banning `interface`:
- Interfaces do not extend `Record` or have a `string` index signature
by default, making them incompatible with the data/state objects we use.
- The feature set of type aliases is a strict superset of that of
interfaces (including `extends`, `implements`).
- Declaration merging is an exception, but this is not a practice we
want to encourage.

For more context, see these links for previous discussions on this
topic:
- MetaMask/eslint-config#216
- MetaMask/core#1933

### Explanation

The `@typescript-eslint/consistent-type-definitions` has been configured
with the `["error", "type"]` options, which will prevent the `interface`
keyword from being introduced into the codebase in the future.

Existing instances of `interface` usage in the codebase were converted
to type alias definitions.

For the following exceptions, the `interface` keyword was preserved with
a `eslint-disable` directive, and a TODO comment was added for future
conversion.

1. If the `interface` is declared with an `extends` keyword.
- This is because of possible type accuracy issues with the eslint
autofix appending the extending interface as an intersection (`&`).
2. If the `interface` is used for declaration merging. 
- This is the only use case for interfaces that is not supported by type
aliases, and is therefore a valid exception to the ESLint rule.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/23439?quickstart=1)

## **Related issues**

- Closes #23442

## **Manual testing steps**

## **Screenshots/Recordings**

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've clearly explained what problem this PR is solving and how it
is solved.
- [x] I've linked related issues
- [ ] I've included manual testing steps
- [ ] I've included screenshots/recordings if applicable
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [x] I’ve properly set the pull request status:
  - [x] In case it's not yet "ready for review", I've set it to "draft".
- [x] In case it's "ready for review", I've changed it from "draft" to
"non-draft".

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Re-enable @typescript-eslint/consistent-type-definitions
4 participants