Skip to content

Problem with snippets and generics when using tseslint recommnedeTypeCheked #658

@maarekj

Description

@maarekj

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I'm using eslint-plugin-svelte. (*.svelte file linting does not work with the parser alone. You should also use eslint-plugin-svelte with it.)
  • I'm sure the problem is a parser problem. (If you are not sure, search for the issue in eslint-plugin-svelte repo and open the issue in eslint-plugin-svelte repo if there is no solution.
  • 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.19.0

What version of eslint-plugin-svelte and svelte-eslint-parser are you using?

  • svelte-eslint-parser@1.0.0-next.13
  • eslint-plugin-svelte@3.0.0-next.17

What did you do?

Configuration
// package.json
{
	"name": "svelte-snippet-bug",
	"private": true,
	"version": "0.0.1",
	"type": "module",
	"scripts": {
		"dev": "vite dev",
		"build": "vite build",
		"preview": "vite preview",
		"prepare": "svelte-kit sync || echo ''",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
		"lint": "eslint ."
	},
	"devDependencies": {
		"@eslint/compat": "^1.2.5",
		"@eslint/js": "^9.19.0",
		"@sveltejs/adapter-auto": "^4.0.0",
		"@sveltejs/kit": "^2.16.0",
		"@sveltejs/vite-plugin-svelte": "^5.0.3",
		"eslint": "^9.19.0",
		"eslint-plugin-svelte": "^3.0.0-next.17",
		"globals": "^15.14.0",
		"svelte": "^5.19.4",
		"svelte-check": "^4.1.4",
		"typescript": "^5.7.3",
		"typescript-eslint": "^8.22.0",
		"vite": "^6.0.11"
	}
}
// eslint.config.js
import js from '@eslint/js';
import {includeIgnoreFile} from '@eslint/compat';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import {fileURLToPath} from 'node:url';
import ts from 'typescript-eslint';

const gitignorePath = fileURLToPath(new URL("./.gitignore", import.meta.url));

export default ts.config(
    includeIgnoreFile(gitignorePath),
    js.configs.recommended,
    ...ts.configs.recommendedTypeChecked,
    ...svelte.configs["flat/recommended"],
    {
        ignores: ["**/*.js", 'node_modules/**/*'],
    },
    {
        languageOptions: {
            globals: {
                ...globals.browser,
                ...globals.node,
            },
            parserOptions: {
                projectService: true,
                tsconfigRootDir: import.meta.dirname,
            },
        },
    },
    {
        files: ["**/*.svelte"],
        languageOptions: {

            parserOptions: {
                parser: ts.parser,
                projectService: true,
                extraFileExtensions: ['.svelte'],
            },
        },
    }
);
// File ChoiceList.svelte

<script lang="ts" generics="TChoice">
    type Props = {
        choices: readonly TChoice[];
        getKey: (choice: TChoice) => string;
        item: import('svelte').Snippet<[{ choice: TChoice }]>,
    }

    const {choices, getKey, item}: Props = $props();
</script>

<ul>
    {#each choices as choice (getKey(choice))}
        <li>{@render item({choice})}</li>
    {/each}
</ul>
// File +page.svelte

<script lang="ts">
    import ChoiceList from "$lib/ChoiceList.svelte";

    let choices = [
        {id: "1", username: "John Doe"},
        {id: "2", username: "Jane Dae"},
    ]
</script>

<ChoiceList {choices} getKey={(choice) => choice.id}>
    {#snippet item({choice})}
        {choice.username}
    {/snippet}
</ChoiceList>

What did you expect to happen?

There are no errors in this code.
So no errors should be raised when running eslint.

What actually happened?

> svelte-snippet-bug@0.0.1 lint
> eslint .


/svelte-snippet-bug/src/routes/+page.svelte
  13:43  error  Unsafe return of a value of type `any`            @typescript-eslint/no-unsafe-return
  13:50  error  Unsafe member access .id on an `any` value        @typescript-eslint/no-unsafe-member-access
  15:17  error  Unsafe member access .username on an `any` value  @typescript-eslint/no-unsafe-member-access

✖ 3 problems (3 errors, 0 warnings)

Link to GitHub Repo with Minimal Reproducible Example

https://github.com/maarekj/svelte-snippet-bug

Additional comments

I use the tselint.configs.recommendedTypeChecked instead of just tseslint.configs.recommended

https://typescript-eslint.io/getting-started/typed-linting

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions