Skip to content

Commit a43d570

Browse files
committed
feat: add no-unused-props rule
1 parent db39572 commit a43d570

File tree

59 files changed

+882
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+882
-0
lines changed

.changeset/twelve-beers-talk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': minor
3+
---
4+
5+
feat: add `no-unused-props` rule

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ These rules relate to better ways of doing things to help you avoid problems:
362362
| [svelte/no-reactive-literals](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-reactive-literals/) | don't assign literal values in reactive statements | :star::bulb: |
363363
| [svelte/no-svelte-internal](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-svelte-internal/) | svelte/internal will be removed in Svelte 6. | :star: |
364364
| [svelte/no-unused-class-name](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-class-name/) | disallow the use of a class in the template without a corresponding style | |
365+
| [svelte/no-unused-props](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-props/) | Warns about defined Props properties that are unused | :star: |
365366
| [svelte/no-unused-svelte-ignore](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-svelte-ignore/) | disallow unused svelte-ignore comments | :star: |
366367
| [svelte/no-useless-children-snippet](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-useless-children-snippet/) | disallow explicit children snippet where it's not needed | :star: |
367368
| [svelte/no-useless-mustaches](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-useless-mustaches/) | disallow unnecessary mustache interpolations | :star::wrench: |

docs/rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ These rules relate to better ways of doing things to help you avoid problems:
5959
| [svelte/no-reactive-literals](./rules/no-reactive-literals.md) | don't assign literal values in reactive statements | :star::bulb: |
6060
| [svelte/no-svelte-internal](./rules/no-svelte-internal.md) | svelte/internal will be removed in Svelte 6. | :star: |
6161
| [svelte/no-unused-class-name](./rules/no-unused-class-name.md) | disallow the use of a class in the template without a corresponding style | |
62+
| [svelte/no-unused-props](./rules/no-unused-props.md) | Warns about defined Props properties that are unused | :star: |
6263
| [svelte/no-unused-svelte-ignore](./rules/no-unused-svelte-ignore.md) | disallow unused svelte-ignore comments | :star: |
6364
| [svelte/no-useless-children-snippet](./rules/no-useless-children-snippet.md) | disallow explicit children snippet where it's not needed | :star: |
6465
| [svelte/no-useless-mustaches](./rules/no-useless-mustaches.md) | disallow unnecessary mustache interpolations | :star::wrench: |

docs/rules/no-unused-props.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/no-unused-props'
5+
description: 'Warns about defined Props properties that are unused'
6+
---
7+
8+
# svelte/no-unused-props
9+
10+
> Warns about defined Props properties that are unused
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
13+
- :gear: This rule is included in `"plugin:svelte/recommended"`.
14+
15+
## :book: Rule Details
16+
17+
This rule reports properties that are defined in Props but never used in the component code.
18+
It helps to detect dead code and improve component clarity by ensuring that every declared prop is utilized.
19+
20+
This rule checks various usage patterns of props:
21+
22+
- Direct property access
23+
- Destructuring assignment
24+
- Method calls
25+
- Computed property access
26+
- Object spread
27+
- Constructor calls (new expressions)
28+
- Assignment to other variables
29+
- Index signatures (e.g. `[key: string]: unknown`)
30+
31+
Additionally, this rule checks if index signatures are properly used. When an index signature is defined but not captured using the rest operator (`...`), the rule will suggest using it.
32+
33+
:warning: This rule requires `@typescript-eslint/parser` to work. Make sure you have installed `@typescript-eslint/parser` and configured it in your ESLint configuration. Therefore, the rule violations cannot be seen in the examples on this page because this documentation does not use `@typescript-eslint/parser`.
34+
35+
<!--eslint-skip-->
36+
37+
```svelte
38+
<!-- ✓ Good Examples -->
39+
<script lang="ts">
40+
/* eslint svelte/no-unused-props: "error" */
41+
// Direct property access
42+
const props: { value: string } = $props();
43+
console.log(props.value);
44+
</script>
45+
```
46+
47+
```svelte
48+
<!-- ✓ Good Examples -->
49+
<script lang="ts">
50+
/* eslint svelte/no-unused-props: "error" */
51+
// Destructuring assignment
52+
const { width, height }: { width: number; height: number } = $props();
53+
console.log(width, height);
54+
</script>
55+
```
56+
57+
```svelte
58+
<!-- ✓ Good Examples -->
59+
<script lang="ts">
60+
/* eslint svelte/no-unused-props: "error" */
61+
// Method calls
62+
const props2: { callback: () => void } = $props();
63+
props2.callback();
64+
</script>
65+
```
66+
67+
```svelte
68+
<!-- ✓ Good Examples -->
69+
<script lang="ts">
70+
/* eslint svelte/no-unused-props: "error" */
71+
// Computed property access
72+
const props3: { 'data-value': string } = $props();
73+
const value = props3['data-value'];
74+
</script>
75+
```
76+
77+
```svelte
78+
<!-- ✓ Good Examples -->
79+
<script lang="ts">
80+
/* eslint svelte/no-unused-props: "error" */
81+
// Constructor calls
82+
const props4: { config: { new (): any } } = $props();
83+
new props4.config();
84+
</script>
85+
```
86+
87+
```svelte
88+
<!-- ✓ Good Examples -->
89+
<script lang="ts">
90+
/* eslint svelte/no-unused-props: "error" */
91+
// Using index signature with rest operator
92+
interface Props {
93+
a: number;
94+
[key: string]: unknown;
95+
}
96+
let { a, ...rest }: Props = $props();
97+
console.log(rest);
98+
</script>
99+
```
100+
101+
```svelte
102+
<!-- ✗ Bad Examples -->
103+
<script lang="ts">
104+
/* eslint svelte/no-unused-props: "error" */
105+
// Unused property 'b'
106+
const props: { a: string; b: number } = $props();
107+
console.log(props.a);
108+
</script>
109+
```
110+
111+
```svelte
112+
<!-- ✗ Bad Examples -->
113+
<script lang="ts">
114+
/* eslint svelte/no-unused-props: "error" */
115+
// Unused property in destructuring
116+
const { x }: { x: number; y: number } = $props();
117+
console.log(x);
118+
</script>
119+
```
120+
121+
```svelte
122+
<!-- ✗ Bad Examples -->
123+
<script lang="ts">
124+
/* eslint svelte/no-unused-props: "error" */
125+
// Unused index signature
126+
interface Props {
127+
a: number;
128+
[key: string]: unknown; // This will be reported
129+
}
130+
let { a }: Props = $props();
131+
</script>
132+
```
133+
134+
## :wrench: Options
135+
136+
Nothing.
137+
138+
## :gear: Required Configuration
139+
140+
This rule requires `@typescript-eslint/parser` to work. Here's an example configuration:
141+
142+
```json
143+
{
144+
"parser": "@typescript-eslint/parser",
145+
"parserOptions": {
146+
"project": "./tsconfig.json"
147+
},
148+
"rules": {
149+
"svelte/no-unused-props": "error"
150+
}
151+
}
152+
```
153+
154+
## :mag: Implementation
155+
156+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts)
157+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/no-unused-props.ts)

packages/eslint-plugin-svelte/src/configs/flat/recommended.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const config: Linter.Config[] = [
3232
'svelte/no-store-async': 'error',
3333
'svelte/no-svelte-internal': 'error',
3434
'svelte/no-unknown-style-directive-property': 'error',
35+
'svelte/no-unused-props': 'error',
3536
'svelte/no-unused-svelte-ignore': 'error',
3637
'svelte/no-useless-children-snippet': 'error',
3738
'svelte/no-useless-mustaches': 'error',

packages/eslint-plugin-svelte/src/rule-types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ export interface RuleOptions {
261261
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-class-name/
262262
*/
263263
'svelte/no-unused-class-name'?: Linter.RuleEntry<SvelteNoUnusedClassName>
264+
/**
265+
* Warns about defined Props properties that are unused
266+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-props/
267+
*/
268+
'svelte/no-unused-props'?: Linter.RuleEntry<[]>
264269
/**
265270
* disallow unused svelte-ignore comments
266271
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-svelte-ignore/

0 commit comments

Comments
 (0)