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

☂️ Type-aware linter #3187

Open
Conaclos opened this issue Jun 12, 2024 · 19 comments
Open

☂️ Type-aware linter #3187

Conaclos opened this issue Jun 12, 2024 · 19 comments
Labels
A-Linter Area: linter L-JavaScript Language: JavaScript and super languages

Comments

@Conaclos
Copy link
Member

Description

This umbrella issue tracks the development of type-aware lint rules.
We first motivate our decision to implement our own type synthesizer, and then present the type-aware rules we intend to implement. In a second section, we present preliminary design material that indicates the high-level direction we want to take.

Motivation

Multiple rules from TypeScript ESLint requires type information. Moreover, several linter rules could be enhanced by using type information.

TypeScript ESLint uses the TypeScript Compiler API to get types. This architecture has the advantage of using the TypeScript Compiler. However, it has several drawbacks:

  • TSC is slow, and using the Compiler API makes the slowness even more noticeable.
    In fact, it is so slow that TypeScript ESLint provides presets with and without the rules that require type information.
  • Biome and TSC use their own AST, which makes interoperability difficult.

This is why we think it is important to implement our own type synthesiser. If we have a fast type synthesiser, then we could enhance many lint rules with a marginal performance overhead. Note that we are not trying to implement a full-fledged type system or a type checker like TypeScript. Many attempt, even the most promising failed.

We believe that the Biome type synthesiser doesn't need to be perfect or handle complex TypeScript types. Even a rudimentary type synthesiser could be valuable to many lint rules.

Type-aware lint rules

A first design and implementation of the Biome type synthesiser aims to implement a preliminary version of the following rules:

  • useAwaitThenable (await-thenable)

    Ensure that only thenable values are awaited. We could first target a rule that ensures that an awaited expression is a Promise. We could ignore values with an unknown type.

  • noFloatingPromises (no-floating-promises)

    Ensure that a promise is handled (returned, awaited, ...).

  • noForInArray (no-for-in-array)

    Ensure that for-in is not used on arrays.

  • noDuplicateLiteralEnumMembers (no-duplicate-enum-values)

    Ensure that every enum member initialized with a literal expression is unique. This doesn't necessarlly requires a type system. We need to compute literal expressions.

Funding

To support this effort, please consider sponsoring Biome within our Open Collective or GitHub sponsorship.

We decide not to fund this issue with Polar.sh because it is a long term effort. Polar.sh is designed for short and medium term efforts. It set a deadline of 6 months to complete a task.

@Conaclos Conaclos added A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Jun 12, 2024
@Conaclos Conaclos pinned this issue Jun 14, 2024
@MrTact
Copy link

MrTact commented Jul 5, 2024

Maybe the approach is to identify the most critical rules, and implement type inference just for the required types? E.g. the first two rules appear to be promise-related, so figure out that a given identifier is a promise. This should still be built on a forward-looking type analyzer architecture, but by constraining the scope, you can make the effort much more manageable, since you don't have to achieve parity with tsc (a fool's errand anyway, which you point out). This also means that, post an admittedly non-trivial chunk of groundwork, additional rules can be developed (and shipped, ideally!) incrementally.

If the duplicate enum rule doesn't require a type checker, it should probably be peeled off into its own issue. Seems like it's bundled here just because it comes from typescript-eslint.

@henrik242

This comment has been minimized.

@Conaclos
Copy link
Member Author

I use tsc --noEmit && biome check . in my package.json. Can I drop tsc? What will I miss if I drop tsc?

Biome doesn't perform type checking and is not intended to do in the future.
Once this issue is resolved, Biome will be able to implement some rules from Typescript ESLint plugin that requires type information.

@scamden

This comment has been minimized.

@krzkaczor

This comment has been minimized.

@scamden

This comment has been minimized.

@krzkaczor

This comment has been minimized.

@trungutt

This comment was marked as off-topic.

@junaga
Copy link

junaga commented Aug 31, 2024

what about just shipping a default tsconfig.json, and then tell|ask|suggest Biome users in the docs to use it?

@testerez
Copy link

Note that we are not trying to implement a full-fledged type system or a type checker like TypeScript

Does it mean that types will be properly identified only when they are explicit? Or will Biome be able to follow complex type inferences?

@ericchase
Copy link

wanted to chime in about

i think this is an extremely important rule. just this past week, i've forgotten to await async functions dozens of times. i had to pull in eslint with just 2 rules related to this to check my code. tsc is so horrendously slow.

i'm not really sure why these few specific rules need type awareness while other rules don't, but i would love to see these rules added!

@awhitford
Copy link

I'd like to share that Astro Starlight cited the lack of a no-floating-promises equivalent was a show-stopper for adopting Biome over ESLint. 😞

@jpike88
Copy link

jpike88 commented Dec 16, 2024

Special request for https://eslint.org/docs/latest/rules/require-await, I really miss that one and it's all related to ensuring that asynchronous code is written cleanly

@arendjr
Copy link
Contributor

arendjr commented Dec 16, 2024

@jpike88 We should be able to implement that one already, since it’s syntax only. I’ve created a task for it: #4747

I should have checked first. We already have it: https://biomejs.dev/linter/rules/use-await/ 😅

@0x80
Copy link

0x80 commented Dec 16, 2024

I should have checked first. We already have it: biomejs.dev/linter/rules/use-await 😅

I feel confused 😅 I was watching this topic waiting for the equivalent of @typescript-eslint/no-floating-promises to arrive before making the jump to Biome, but now you're saying that it existed all along and doesn't even need type information? 🤔

That's great news, if I didn't misunderstand it somehow...

The other ones I'd be interested in are @typescript-eslint/no-misused-promises and @typescript-eslint/await-thenable but those are not essential to me.

@dyc3
Copy link
Contributor

dyc3 commented Dec 16, 2024

No, we have the equivalent of require-await, not no-floating-promises. useAwait only enforces that an await appears in an async function.

@misl-smlz

This comment has been minimized.

@0x80

This comment has been minimized.

@karlkeefer
Copy link

I just became a supporter of the project with this issue in mind. This would be a great addition to biome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Linter Area: linter L-JavaScript Language: JavaScript and super languages
Projects
None yet
Development

No branches or pull requests