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

Forbid TypeScript interfaces #216

Merged
merged 1 commit into from
Dec 15, 2021
Merged

Forbid TypeScript interfaces #216

merged 1 commit into from
Dec 15, 2021

Conversation

rekmarks
Copy link
Member

@rekmarks rekmarks commented Nov 29, 2021

TypeScript interfaces suck, they don't work with our Json type, and it's high time that we abolish them from every part of our codebase.

To wit, the only thing that can be done with an interface that cannot be done with a type is declaration merging, which is a "good language feature" in much the same way that a knife without a handle is a "good cooking instrument". All of the actually good stuff – IMO first and foremost extends and implementsis also supported by object types (in this case, via & and implements).

So, if we have two language features A and B, where the capabilities of A are a strict superset of those of B, and using B at all will sometimes cause uses supported by A to fail, the only sane thing to do is get rid of B. "B" is interfaces. Long live interfaces!

@rekmarks rekmarks requested a review from a team as a code owner November 29, 2021 21:35
@rekmarks rekmarks force-pushed the forbid-typescript-interfaces branch from f85d1a3 to 0030943 Compare November 29, 2021 21:39
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

Might want to link to the Slack thread so people can understand the rationale behind this, but regardless, I'm cool with this. I've never had to use an interface, personally.

@rekmarks
Copy link
Member Author

@mcmire updated description for clarity!

@rekmarks rekmarks merged commit ec27156 into main Dec 15, 2021
@rekmarks rekmarks deleted the forbid-typescript-interfaces branch December 15, 2021 22:14
rekmarks added a commit to MetaMask/key-tree that referenced this pull request Dec 15, 2021
We hate interfaces, and they must be driven from this Earth in favor of object types.

Ref: MetaMask/eslint-config#216
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.

2 participants