Skip to content

Commit 842757f

Browse files
authoredApr 1, 2025··
feat(no-unused-props): add allowUnusedNestedProperties option (#1171)
1 parent 7892f4c commit 842757f

File tree

8 files changed

+75
-3
lines changed

8 files changed

+75
-3
lines changed
 

‎.changeset/fancy-trams-create.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': minor
3+
---
4+
5+
feat(no-unused-props): add `allowUnusedNestedProperties` option

‎docs/rules/no-unused-props.md

+18
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,16 @@ Note: Properties of class types are not checked for usage, as they might be used
163163
"ignoreTypePatterns": [],
164164
// Patterns to ignore when checking for unused props
165165
"ignorePropertyPatterns": [],
166+
// Whether to allow unused nested properties
167+
"allowUnusedNestedProperties": false
166168
}]
167169
}
168170
```
169171

170172
- `checkImportedTypes` ... Controls whether to check properties from types defined in external files. Default is `false`, meaning the rule only checks types defined within the component file itself. When set to `true`, the rule will also check properties from imported and extended types.
171173
- `ignoreTypePatterns` ... Regular expression patterns for type names to exclude from checks. Default is `[]` (no exclusions). Most useful when `checkImportedTypes` is `true`, allowing you to exclude specific imported types (like utility types or third-party types) from being checked.
172174
- `ignorePropertyPatterns` ... Regular expression patterns for property names to exclude from unused checks. Default is `[]` (no exclusions). Most useful when `checkImportedTypes` is `true`, allowing you to ignore specific properties from external types that shouldn't trigger warnings.
175+
- `allowUnusedNestedProperties` ... Controls whether to allow unused nested properties. Default is `false`, meaning the rule will report unused properties from nested objects.
173176

174177
Examples:
175178

@@ -219,6 +222,21 @@ Examples:
219222
</script>
220223
```
221224

225+
```svelte
226+
<!-- ✓ Good Example with allowUnusedNestedProperties: true -->
227+
<script lang="ts">
228+
/* eslint svelte/no-unused-props: ["error", { "allowUnusedNestedProperties": true }] */
229+
interface Props {
230+
user: {
231+
name: string;
232+
age: number; // Won't be reported as unused
233+
};
234+
}
235+
let { user }: Props = $props();
236+
console.log(user.name);
237+
</script>
238+
```
239+
222240
## :gear: Required Configuration
223241

224242
This rule requires `@typescript-eslint/parser` to work. Please refer to the [User Guide](../user-guide.md) for more information.

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

+1
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ type SvelteNoUnusedProps = []|[{
537537
checkImportedTypes?: boolean
538538
ignoreTypePatterns?: string[]
539539
ignorePropertyPatterns?: string[]
540+
allowUnusedNestedProperties?: boolean
540541
}]
541542
// ----- svelte/no-useless-mustaches -----
542543
type SvelteNoUselessMustaches = []|[{

‎packages/eslint-plugin-svelte/src/rules/no-unused-props.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ export default createRule('no-unused-props', {
3838
type: 'string'
3939
},
4040
default: []
41+
},
42+
allowUnusedNestedProperties: {
43+
type: 'boolean',
44+
default: false
4145
}
4246
},
4347
additionalProperties: false
@@ -356,7 +360,10 @@ export default createRule('no-unused-props', {
356360
return declaredPropertyNames.size === 0;
357361
}
358362

359-
function normalizeUsedPaths(paths: PropertyPathArray[]): PropertyPathArray[] {
363+
function normalizeUsedPaths(
364+
paths: PropertyPathArray[],
365+
allowUnusedNestedProperties: boolean
366+
): PropertyPathArray[] {
360367
const normalized: PropertyPathArray[] = [];
361368
for (const path of paths.sort((a, b) => a.length - b.length)) {
362369
if (path.length === 0) continue;
@@ -365,7 +372,11 @@ export default createRule('no-unused-props', {
365372
}
366373
normalized.push(path);
367374
}
368-
return normalized;
375+
return normalized.map((path) => {
376+
// If we allow unused nested properties, only return first level properties
377+
if (allowUnusedNestedProperties) return [path[0]];
378+
return path;
379+
});
369380
}
370381

371382
return {
@@ -410,7 +421,10 @@ export default createRule('no-unused-props', {
410421

411422
checkUnusedProperties({
412423
propsType,
413-
usedPropertyPaths: normalizeUsedPaths(usedPropertyPathsArray).map((pathArray) => {
424+
usedPropertyPaths: normalizeUsedPaths(
425+
usedPropertyPathsArray,
426+
options.allowUnusedNestedProperties
427+
).map((pathArray) => {
414428
return pathArray.join('.');
415429
}),
416430
declaredPropertyNames,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"options": [
3+
{
4+
"allowUnusedNestedProperties": true
5+
}
6+
]
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script lang="ts">
2+
interface Props {
3+
user: {
4+
name: string;
5+
location: string;
6+
};
7+
}
8+
let props: Props = $props();
9+
console.log(props.user.name);
10+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"options": [
3+
{
4+
"allowUnusedNestedProperties": true
5+
}
6+
]
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script lang="ts">
2+
interface Props {
3+
user: {
4+
name: string;
5+
age: number; // Won't be reported as unused
6+
};
7+
}
8+
let { user }: Props = $props();
9+
console.log(user.name);
10+
</script>

0 commit comments

Comments
 (0)
Please sign in to comment.