diff --git a/.changeset/plain-chairs-tie.md b/.changeset/plain-chairs-tie.md new file mode 100644 index 000000000..5b5c46d5d --- /dev/null +++ b/.changeset/plain-chairs-tie.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': patch +--- + +fix: correct detection of externally defined types in `no-unused-props` rule 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 0d057b3f0..d425026f2 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts @@ -80,15 +80,11 @@ export default createRule('no-unused-props', { return shouldIgnore(typeStr) || (symbolName ? shouldIgnore(symbolName) : false); } - function isExternalType(type: ts.Type): boolean { - const symbol = type.getSymbol(); - if (!symbol) return false; - + function isInternalProperty(symbol: ts.Symbol): boolean { const declarations = symbol.getDeclarations(); if (!declarations || declarations.length === 0) return false; - const sourceFile = declarations[0].getSourceFile(); - return sourceFile.fileName !== fileName; + return declarations.every((decl) => decl.getSourceFile().fileName === fileName); } /** @@ -200,7 +196,6 @@ export default createRule('no-unused-props', { if (checkedTypes.has(typeStr)) return; checkedTypes.add(typeStr); if (shouldIgnoreType(type)) return; - if (!checkImportedTypes && isExternalType(type)) return; const properties = typeChecker.getPropertiesOfType(type); const baseTypes = type.getBaseTypes(); @@ -225,6 +220,7 @@ export default createRule('no-unused-props', { for (const prop of properties) { if (isBuiltInProperty(prop)) continue; + if (!checkImportedTypes && !isInternalProperty(prop)) continue; const propName = prop.getName(); const currentPath = [...parentPath, propName]; diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-errors.yaml new file mode 100644 index 000000000..502c15458 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-errors.yaml @@ -0,0 +1,4 @@ +- message: "'child2' is an unused Props property." + line: 9 + column: 6 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-input.svelte new file mode 100644 index 000000000..2d26bd2d9 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-input.svelte @@ -0,0 +1,10 @@ + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml index 2f341476f..278805b2d 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml @@ -1,6 +1,4 @@ - message: "'name' is an unused Props property." line: 6 column: 6 - endLine: 6 - endColumn: 20 suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts index a60e61ef1..e33a3a24e 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts @@ -1,3 +1,14 @@ export interface BaseProps { name: string; } + +export interface FooDTO { + foo: string; + bar: number; + baz: BazDTO; +} + +interface BazDTO { + qux: string; + quux: number; +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-external-type-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-external-type-input.svelte new file mode 100644 index 000000000..920dece77 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-external-type-input.svelte @@ -0,0 +1,10 @@ + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts index a60e61ef1..e33a3a24e 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts @@ -1,3 +1,14 @@ export interface BaseProps { name: string; } + +export interface FooDTO { + foo: string; + bar: number; + baz: BazDTO; +} + +interface BazDTO { + qux: string; + quux: number; +}