diff --git a/.changeset/fancy-trams-create.md b/.changeset/fancy-trams-create.md new file mode 100644 index 000000000..b9416a5f7 --- /dev/null +++ b/.changeset/fancy-trams-create.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': minor +--- + +feat(no-unused-props): add `allowUnusedNestedProperties` option diff --git a/docs/rules/no-unused-props.md b/docs/rules/no-unused-props.md index fffe3864f..33f1f0804 100644 --- a/docs/rules/no-unused-props.md +++ b/docs/rules/no-unused-props.md @@ -163,6 +163,8 @@ Note: Properties of class types are not checked for usage, as they might be used "ignoreTypePatterns": [], // Patterns to ignore when checking for unused props "ignorePropertyPatterns": [], + // Whether to allow unused nested properties + "allowUnusedNestedProperties": false }] } ``` @@ -170,6 +172,7 @@ Note: Properties of class types are not checked for usage, as they might be used - `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. - `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. - `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. +- `allowUnusedNestedProperties` ... Controls whether to allow unused nested properties. Default is `false`, meaning the rule will report unused properties from nested objects. Examples: @@ -219,6 +222,21 @@ Examples: ``` +```svelte + + +``` + ## :gear: Required Configuration This rule requires `@typescript-eslint/parser` to work. Please refer to the [User Guide](../user-guide.md) for more information. diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index 19e30a345..7b5cf238c 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -537,6 +537,7 @@ type SvelteNoUnusedProps = []|[{ checkImportedTypes?: boolean ignoreTypePatterns?: string[] ignorePropertyPatterns?: string[] + allowUnusedNestedProperties?: boolean }] // ----- svelte/no-useless-mustaches ----- type SvelteNoUselessMustaches = []|[{ diff --git a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts index 61b60e99e..01621f205 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts @@ -37,6 +37,10 @@ export default createRule('no-unused-props', { type: 'string' }, default: [] + }, + allowUnusedNestedProperties: { + type: 'boolean', + default: false } }, additionalProperties: false @@ -342,7 +346,10 @@ export default createRule('no-unused-props', { return usedProps.size === 0; } - function normalizeUsedPaths(paths: PropertyPathArray[]): PropertyPathArray[] { + function normalizeUsedPaths( + paths: PropertyPathArray[], + allowUnusedNestedProperties: boolean + ): PropertyPathArray[] { const normalized: PropertyPathArray[] = []; for (const path of paths.sort((a, b) => a.length - b.length)) { if (path.length === 0) continue; @@ -351,7 +358,11 @@ export default createRule('no-unused-props', { } normalized.push(path); } - return normalized; + return normalized.map((path) => { + // If we allow unused nested properties, only return first level properties + if (allowUnusedNestedProperties) return [path[0]]; + return path; + }); } return { @@ -396,7 +407,10 @@ export default createRule('no-unused-props', { checkUnusedProperties({ propsType, - usedPropertyPaths: normalizeUsedPaths(usedPropertyPathsArray).map((pathArray) => { + usedPropertyPaths: normalizeUsedPaths( + usedPropertyPathsArray, + options.allowUnusedNestedProperties + ).map((pathArray) => { return pathArray.join('.'); }), declaredPropertyNames, diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused-config.json new file mode 100644 index 000000000..57afa3f3f --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused-config.json @@ -0,0 +1,7 @@ +{ + "options": [ + { + "allowUnusedNestedProperties": true + } + ] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused-input.svelte new file mode 100644 index 000000000..8293761a6 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused-input.svelte @@ -0,0 +1,10 @@ + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused2-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused2-config.json new file mode 100644 index 000000000..57afa3f3f --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused2-config.json @@ -0,0 +1,7 @@ +{ + "options": [ + { + "allowUnusedNestedProperties": true + } + ] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused2-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused2-input.svelte new file mode 100644 index 000000000..0d38a3136 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-unused2-input.svelte @@ -0,0 +1,10 @@ +