svelte-eslint-parser icon indicating copy to clipboard operation
svelte-eslint-parser copied to clipboard

False positive TypeScript ESLint errors when using slot props

Open rowanlovejoy opened this issue 1 year ago • 0 comments

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

  • [X] 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.)
  • [X] 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.
  • [X] I have tried restarting my IDE and the issue persists.
  • [X] I have updated to the latest version of the packages.

What version of ESLint are you using?

8.47.0

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

What did you do?

Configuration

module.exports = { extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended-type-checked', 'plugin:svelte/recommended', ], parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint'], parserOptions: { project: true, tsconfigRootDir: __dirname, extraFileExtensions: ['.svelte'], }, overrides: [ { files: ['*.svelte'], parser: 'svelte-eslint-parser', parserOptions: { parser: '@typescript-eslint/parser', }, }, ], root: true, env: { browser: true, node: true, }, };

// App.svelte
<script lang="ts">
	import CustomList from './lib/CustomList.svelte';
	import type { ListItem } from './lib/types';

	const items: ListItem[] = [
		{
			title: 'Svelte.dev',
			link: 'https://svelte.dev',
		},
		{
			title: 'TypeScript ESLint',
			link: 'https://typescript-eslint.io',
		},
		{
			title: 'TypeScript',
			link: 'https://www.typescriptlang.org',
		},
	];

	const openLink = (item: ListItem) => {
		window.location.replace(item.link);
	};
</script>

<main>
	<CustomList
		{items}
		let:item
	>
		<div>
			{item.title}
			<button
				on:click={() => {
					openLink(item);
				}}>Open Link</button
			>
		</div>
	</CustomList>
</main>


// CustomList.svelte
<script lang="ts">
	import type { ListItem } from './types';

	export let items: ListItem[];
</script>

<div>
	<ul>
		{#each items as item (item.title)}
			<li>
				<slot {item} />
			</li>
		{/each}
	</ul>
</div>
// types.ts
export interface ListItem {
	title: string;
	link: string;
}

What did you expect to happen?

No ESLint errors or warnings are raised for the code, as the types are defined and compatible with how they are being used.

What actually happened?

ESLint raises two errors. The first, @typescript-eslint/no-unsafe-member-access, when accessing the title property of the item slot prop; the second, @typescript-eslint/no-unsafe-argument, passing the item slot prop to the openLink function.

Link to GitHub Repo with Minimal Reproducible Example

https://github.com/rowanlovejoy/eslint-svelte-test

Additional comments

The minimal reproduction repo is based on the Vite Svelte template described here: https://vitejs.dev/guide/#scaffolding-your-first-vite-project It includes additional package.json commands to run ESLint and the TypeScript compiler independently. It uses PNPM.

The template code of the App.svelte component demonstrates the linting error.

The app renders a list of items. Each item includes a title and a link. For each item, the title is rendered along with a button to open that link in the current browser tab.

I believe this is a parsing problem because this issue occurs only on the template (which I understand the parser transforms into an AST; apologies if this is incorrect, I've never worked on anything like this); the TypeScript compiler correctly understands the code; the errors being raised are not eslint-plugin-svelte ruleset; and I've used this same configuration in React TypeScript projects with almost identical code and not experienced similar problems.

rowanlovejoy avatar Aug 15 '23 21:08 rowanlovejoy