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

Rule proposal: Ban 'in' operator for arrays #5474

Closed
6 tasks done
ZhangYiJiang opened this issue Aug 14, 2022 · 11 comments
Closed
6 tasks done

Rule proposal: Ban 'in' operator for arrays #5474

ZhangYiJiang opened this issue Aug 14, 2022 · 11 comments
Labels
duplicate This issue or pull request already exists enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@ZhangYiJiang
Copy link

ZhangYiJiang commented Aug 14, 2022

Before You File a Proposal Please Confirm You Have Done The Following...

My proposal is suitable for this project

  • My proposal specifically checks TypeScript syntax, or it proposes a check that requires type information to be accurate.
  • My proposal is not a "formatting rule"; meaning it does not just enforce how code is formatted (whitespace, brace placement, etc).
  • I believe my proposal would be useful to the broader TypeScript community (meaning it is not a niche proposal).

Description

Checking for array membership using in is a common new JS developer mistake - it looks like it should work but it does not since in checks for properties, and array values are not properties.

Fail Cases

const arr = ['a', 'b', 'c'];
const inArray = 'a' in arr;

Pass Cases

const arr = ['a', 'b', 'c'];
const inArray = arr.includes('a');

Additional Info

There is a very similar https://typescript-eslint.io/rules/no-for-in-array rule for for-in loops specifically

@ZhangYiJiang ZhangYiJiang added enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Aug 14, 2022
@JoshuaKGoldberg JoshuaKGoldberg added accepting prs Go ahead, send a pull request that resolves this issue and removed triage Waiting for maintainers to take a look labels Aug 16, 2022
@JoshuaKGoldberg
Copy link
Member

SGTM! As stated & with no-for-in-array, this will have to be a typed rule, to know whether a value is an array.

@juank1809
Copy link
Contributor

I'd like to work on this issue! though it will take me some time.

@mahdi-farnia
Copy link

✅ Just needs a review

@bradzacher
Copy link
Member

@JoshuaKGoldberg i wonder if we should merge this with #5677

It seems like they're doing the same thing, except #5677 covers more cases.

@mahdi-farnia
Copy link

@JoshuaKGoldberg i wonder if we should merge this with #5677

It seems like they're doing the same thing, except #5677 covers more cases.

I agree, but i think it should be too hard.
In JavaScript everything is an object and has proprties (except null and undefined) that those property has other properties... (prototype chaining)
What is the standard way to detect indexables?

@bradzacher
Copy link
Member

@mahdi-farnia by using types! All of the relevant information is available on the types.

You can play around in https://ts-ast-viewer.com to get a feel for how different cases might look.

Grep our codebase fir getProp and you'll find some property lookup examples.

Your code is a good special case message to start with - but we should do more than just arrays if we can!

@mahdi-farnia
Copy link

@bradzacher I've done exploring and working with astexplorer.
I'll check that link too!

But my question remains: which types are indexable?
Arrays & PlainObjects only?

@bradzacher
Copy link
Member

Any type with an index signature is indexable.

Eg

type T = { [k: string]: number}

But we should still ensure we disallow string likes and arrays

@mahdi-farnia
Copy link

@bradzacher
Typescript already raises error for string type. (String indexes are readonly)
But distinguish types that have index signature is impossible (isn't it?)

As i said everything in JavaScript is a pair of keys and values: Record<PropertyKey, any>
In my opinion these scenarios are possible:

  1. Ban delete at all
  2. Disallow delete for index of type numbers for arrays (better)

@JoshuaKGoldberg
Copy link
Member

But distinguish types that have index signature is impossible (isn't it?)

You can use the type checker for this. Just playing around on my end, I do see an '__index' type declared in the symbol for let temp: { [i: string]: string } = {}'s backing type. Array.from(type.symbol.members[0]). You'll have to play with a bit on your end.

@JoshuaKGoldberg
Copy link
Member

JoshuaKGoldberg commented Oct 20, 2022

@JoshuaKGoldberg i wonder if we should merge this with #5677
It seems like they're doing the same thing, except #5677 covers more cases.

Agreed, good point. no-misused-in would cover this case anyway.

Closing this as a dup. Thanks for the discussion all!

@JoshuaKGoldberg JoshuaKGoldberg added duplicate This issue or pull request already exists and removed accepting prs Go ahead, send a pull request that resolves this issue labels Oct 20, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
duplicate This issue or pull request already exists enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants