-
-
Notifications
You must be signed in to change notification settings - Fork 56
Description
Before You File a Bug Report Please Confirm You Have Done The Following...
- I have tried restarting my IDE and the issue persists.
- I have updated to the latest version of the packages.
What version of ESLint are you using?
9.34.0
What version of eslint-plugin-svelte
are you using?
3.12.2
What did you do?
I created a Svelte layout file, defined the props return type, but intentionally left one of the properties unused. The svelte/no-unused-props rule
was never triggered on Windows. However, on Linux and macOS, ESLint correctly reported the unused prop as an error when linting the file.
Configuration
import prettier from 'eslint-config-prettier';
import { includeIgnoreFile } from '@eslint/compat';
import js from '@eslint/js';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import { fileURLToPath } from 'node:url';
import ts from 'typescript-eslint';
import svelteConfig from './svelte.config.js';
const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));
export default ts.config(
includeIgnoreFile(gitignorePath),
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs.recommended,
prettier,
...svelte.configs.prettier,
{
languageOptions: {
globals: { ...globals.browser, ...globals.node }
},
rules: {
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
'no-undef': 'off'
}
},
{
files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
languageOptions: {
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig
}
}
}
);
<script lang="ts">
import type { Snippet } from 'svelte';
import type { LayoutData } from './$types';
let { children }: { data: LayoutData; children: Snippet } = $props();
</script>
{@render children?.()}
What did you expect to happen?
I expected this snippet to trigger the rule, since the data
field is declared in the type but not used.
What actually happened?
The rule is never applied, ESLint does not report any errors. This was tested on GitHub Runners and locally, and the issue only occurs in Windows environments. Linux and macOS are unaffected.
Link to GitHub Repo with Minimal Reproducible Example
https://github.com/InkedCat/no-unused-props-bug-env
Here is a link to one of my CI run where the bug happened: https://github.com/InkedCat/Vault-Launcher/actions/runs/17535461642
Additional comments
I've done some debugging and believe I've found the source of the bug. In the checkUnusedProperties
function (line 240 of no-unused-props.ts), the for (const prop of properties)
loop checks whether properties are imported types or from internal sources. The isInternalProperty
function in the same file compares the source file path inferred by Typescript declarations with the one passed down by ESLint.
The issue arises from how file paths are handled on Windows: ESLint does normalize the paths (they contains double back slashes, \\
), whereas Typescript does not and gets Windows like paths. Therefore the property is considered internal because the paths are differents.
Path format example:
Eslint: C:\\Users\\...\\VaultLauncher\\src\\lib\\components\\navbar\\nav-main.svelte
Typescript: C:/Users/.../VaultLauncher/src/lib/components/navbar/nav-main.svelte
After applying a small local patch to normalize the Typescript path, the rule is now correctly triggered on Windows.
function isInternalProperty(symbol: ts.Symbol): boolean {
const declarations = symbol.getDeclarations();
if (!declarations || declarations.length === 0) return false;
return declarations.every(
(decl) => path.normalize(decl.getSourceFile().fileName) === fileName
);
}
If needed, I can take some time to open a PR and fix this 👍