Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork2.8k
feat(eslint-plugin): [no-misused-spread] add new rule#10551
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
JoshuaKGoldberg merged 78 commits intotypescript-eslint:mainfromJoshuaKGoldberg:no-misused-spread-ii-electric-boogalooJan 13, 2025
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
78 commits Select commitHold shift + click to select a range
75812fc
feat(eslint-plugin): [no-misused-spread] add new rule
StyleShitf18acb8
fix docs
StyleShit22a50e5
add tests
StyleShit985795a
wip
StyleShit3ff215f
fix functions
StyleShit8e760e0
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit5f9fae6
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit990006f
change type name to `Iterable`
StyleShit49692d2
wip
StyleShit1f76659
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShitc45038f
fix lint
StyleShita12c9ff
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit9f07bc1
wip
StyleShitab20e73
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit3ef5a45
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShitb97a397
wip
StyleShite02d7a9
don't flag strings spread in object
StyleShit26434c3
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit0921b80
wip
StyleShitb8d7e47
wip
StyleShit3f9d545
configs
StyleShitb133698
snapshot
StyleShitc449dba
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShitbb3031f
add options
StyleShit99c67a0
better message
StyleShitef12015
add map
StyleShitc3fa340
messages
StyleShitbc3bcf2
array
StyleShit137c371
promise + iterable
StyleShitdb72726
class declaration
StyleShit92140f2
class instance
StyleShit8a5e2dc
lint
StyleShitd2fe874
wip
StyleShit0b0ac03
docs
StyleShit8a1a309
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShitdc1411f
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit02d7fd3
wip
StyleShite90385a
wip
StyleShitfc57f13
wip
StyleShita95cd5f
wip?
StyleShit094ae02
wip
StyleShitf9a1d18
FML
StyleShite20e49b
wip
StyleShitacd146f
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShitaf82cbb
update snapshot
StyleShit9ff1ba1
docs
StyleShitf4cf064
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit3dea4cd
Merge branch 'main' into feat/no-misused-spread
bradzacher235ca44
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShita808081
Merge branch 'feat/no-misused-spread' of https://github.com/StyleShit…
StyleShit9405682
wip
StyleShit2d60b29
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShita678af7
Merge branch 'main' into feat/no-misused-spread
JoshuaKGoldberg283bbb7
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShit804fab4
Merge branch 'feat/no-misused-spread' of https://github.com/StyleShit…
StyleShitfc0e114
fix tests
StyleShit07b69b8
Merge remote-tracking branch 'typescript-eslint/main' into feat/no-mi…
StyleShitac351e8
Merge branch 'main' into no-misused-spread-ii-electric-boogaloo
JoshuaKGoldberge8a657e
First round of PR feedback
JoshuaKGoldberg20a3ae0
lil docs nit
JoshuaKGoldbergc85797a
More intentional docs reworking
JoshuaKGoldberg714dde6
fix NotFound/Content/index.tsx violation
JoshuaKGoldberg462f811
yarn lint --fix
JoshuaKGoldberg39daadf
Handle static class-likes
JoshuaKGoldberg500d1c1
test -u and cleanup and typo fix
JoshuaKGoldbergd8e8ead
Clean up a few redundant tests
JoshuaKGoldberga04df3b
Also test : unknown
JoshuaKGoldbergb78c27b
Merge branch 'main' into no-misused-spread-ii-electric-boogaloo
JoshuaKGoldbergf49b88f
empty
JoshuaKGoldberge1e9c2c
Fix .mdx docs test
JoshuaKGoldbergb0c3919
Separate TSConfig for DOM
JoshuaKGoldbergca44d93
Handle function call spreads too
JoshuaKGoldbergb0d94e8
Test constrained type params too
JoshuaKGoldbergf3dbde3
Spring
JoshuaKGoldberg6031579
Union type tests
JoshuaKGoldberg5e217c9
Update docs snapshot as well
JoshuaKGoldbergb8a15a1
Merge branch 'main' into no-misused-spread-ii-electric-boogaloo
JoshuaKGoldbergb52123d
HTMLElementLike
JoshuaKGoldbergFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
132 changes: 132 additions & 0 deletionspackages/eslint-plugin/docs/rules/no-misused-spread.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
--- | ||
description: 'Disallow using the spread operator when it might cause unexpected behavior.' | ||
--- | ||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
> 🛑 This file is source code, not the primary documentation location! 🛑 | ||
> | ||
> See **https://typescript-eslint.io/rules/no-misused-spread** for documentation. | ||
[Spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) (`...`) is a JavaScript feature for creating an object with the joined properties of one or more other objects. | ||
TypeScript allows spreading objects whose properties are not typically meant to be enumerated, such as arrays and class instances. | ||
This rule disallows using the spread syntax on values whose types indicate doing so may cause unexpected behavior. | ||
That includes the following cases: | ||
- Spreading a `Promise` into an object. | ||
You probably meant to `await` it. | ||
- Spreading a function without properties into an object. | ||
You probably meant to call it. | ||
- Spreading an iterable (`Array`, `Map`, etc.) into an object. | ||
Iterable objects usually do not have meaningful enumerable properties and you probably meant to spread it into an array instead. | ||
- Spreading a string into an array. | ||
String enumeration behaviors in JavaScript around encoded characters are often surprising. | ||
- Spreading a `class` into an object. | ||
This copies all static own properties of the class, but none of the inheritance chain. | ||
- Spreading a class instance into an object. | ||
This does not faithfully copy the instance because only its own properties are copied, but the inheritance chain is lost, including all its methods. | ||
## Examples | ||
<Tabs> | ||
<TabItem value="❌ Incorrect"> | ||
```ts | ||
declare const promise: Promise<number>; | ||
const spreadPromise = { ...promise }; | ||
declare function getObject(): Record<string, strings>; | ||
const getObjectSpread = { ...getObject }; | ||
declare const map: Map<string, number>; | ||
const mapSpread = { ...map }; | ||
declare const userName: string; | ||
const characters = [...userName]; | ||
``` | ||
```ts | ||
declare class Box { | ||
value: number; | ||
} | ||
const boxSpread = { ...Box }; | ||
declare const instance: Box; | ||
const instanceSpread = { ...box }; | ||
``` | ||
</TabItem> | ||
<TabItem value="✅ Correct"> | ||
```ts | ||
declare const promise: Promise<number>; | ||
const spreadPromise = { ...(await promise) }; | ||
declare function getObject(): Record<string, strings>; | ||
const getObjectSpread = { ...getObject() }; | ||
declare const map: Map<string, number>; | ||
const mapObject = Object.fromEntries(map); | ||
declare const userName: string; | ||
const characters = userName.split(''); | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
## Options | ||
### `allow` | ||
{/* insert option description */} | ||
This option takes the shared [`TypeOrValueSpecifier` format](/packages/type-utils/type-or-value-specifier). | ||
Examples of a configuration for this option in a `file.ts` file: | ||
```json | ||
"@typescript-eslint/no-misused-spread": [ | ||
"error", | ||
{ | ||
"allow": [ | ||
{ "from": "file", "name": "BrandedString", "path": "file.ts" }, | ||
] | ||
} | ||
] | ||
``` | ||
<Tabs> | ||
<TabItem value="❌ Incorrect"> | ||
```ts option='{"allow":[{ "from": "file", "name": "BrandedString" }]}' | ||
declare const unbrandedString: string; | ||
const spreadUnbrandedString = [...unbrandedString]; | ||
``` | ||
</TabItem> | ||
<TabItem value="✅ Correct"> | ||
```ts option='{"allow":[{ "from": "file", "name": "BrandedString" }]}' | ||
type BrandedString = string & { __brand: 'safe' }; | ||
declare const brandedString: BrandedString; | ||
const spreadBrandedString = [...brandedString]; | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
## When Not To Use It | ||
If your application intentionally works with raw data in unusual ways, such as directly manipulating class prototype chains, you might not want this rule. | ||
If your use cases for unusual spreads only involve a few types, you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) and/or the [`allow` option](#allow) instead of completely disabling this rule. | ||
## Further Reading | ||
- [Strings Shouldn't Be Iterable By Default](https://www.xanthir.com/b4wJ1) |
1 change: 1 addition & 0 deletionspackages/eslint-plugin/src/configs/all.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletionspackages/eslint-plugin/src/configs/disable-type-checked.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletionspackages/eslint-plugin/src/configs/strict-type-checked-only.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletionspackages/eslint-plugin/src/configs/strict-type-checked.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletionspackages/eslint-plugin/src/rules/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.