Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte 5: When extracting props from the $props rune typescript eslint errors with unsafe assignment, even though the type is defined following the documentation #804

Open
2 tasks done
victoragcosta opened this issue Jun 20, 2024 · 3 comments

Comments

@victoragcosta
Copy link

victoragcosta commented Jun 20, 2024

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.5.0

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

2.40.0

What did you do?

Configuration
import tsParser from "@typescript-eslint/parser";
import svelteParser from "svelte-eslint-parser";
import ts from "typescript-eslint";
import tsPlugin from "@typescript-eslint/eslint-plugin"
import svelteConfig from "./svelte.config.mjs";

export default ts.config(
	{
		ignores: [
			// Root JS and TS (not included in tsconfig.json and I'm lazy)
			"*.{js,cjs,mjs}",
			"*.{ts,cts,mts}",
		],
		languageOptions: {
			parser: tsParser,
			parserOptions: {
				project: true, 
				// `programs` was giving some weird errors even though I wasn't using this config
				programs: false,
				tsconfigRootDir: import.meta.dirname,
				extraFileExtensions: [".svelte"],
			},
		},
		rules: {
			'@typescript-eslint/no-unsafe-assignment': 'error'
		},
		plugins: {
			'@typescript-eslint': tsPlugin,
		}
	},
	{
		files: ["**/*.svelte", "*.svelte"],
		languageOptions: {
			parser: svelteParser,
			parserOptions: {
				parser: tsParser,
				svelteConfig,
			},
		},
	},
	{
		ignores: [
			// IDEs
			".vscode/*",
			"!.vscode/extensions.json",
			"!.vscode/settings.json",
			// Autogenerated files
			".svelte-kit",
			".DS_Store",
			"node_modules",
			"/build",
			"/package",
			"*.local",
			// Lock files
			"pnpm-lock.yaml",
			"package-lock.json",
			"yarn.lock",
			"bun.lockb",
		],
	},
);
<script lang="ts">
	import type { Snippet } from "svelte";

	interface LayoutProps {
		children: Snippet;
	}

	// This generates the error Unsafe assignment of an `any` value. [@typescript-eslint/no-unsafe-assignment]
	let { children }: LayoutProps = $props();
</script>

{@render children()}

I created a new SvelteKit project and configured it with Svelte 5 to use runes. I used Bun as my package manager and runtime. After that I tried to create a layout file and use runes mode, but when setting up the $props so the layout could accept children I wasn't able to type it the same way that the Svelte's documentation uses it. I can work around it by adding as LayoutProps after $props(), but this feels wrong considering the documentation didn't explicitly say to typecast. I have also tested with non-route components and it also happens.

What did you expect to happen?

I expected that when I typed the $props rune exactly as informed by the Svelte 5 preview documentation I would get no errors of unsafe any assignments.

What actually happened?

/home/victor/pessoal/keyboard-visualizer/src/lib/TestComponent.svelte
  9:6  error  Unsafe assignment of an `any` value  @typescript-eslint/no-unsafe-assignment

/home/victor/pessoal/keyboard-visualizer/src/routes/+layout.svelte
  9:6  error  Unsafe assignment of an `any` value  @typescript-eslint/no-unsafe-assignment

✖ 2 problems (2 errors, 0 warnings)

error: "eslint" exited with code 1

It detected getting the props for the component as an unsafe assignment.

Link to GitHub Repo with Minimal Reproducible Example

https://github.com/victoragcosta/eslint-plugin-svelte-props-unsafe-assignment-repro

Additional comments

Edit: I have tested it now and this also happens if I use npm and node instead of bun.

@kkirkfield
Copy link

A workaround right now is to use a type assertion.

<script lang="ts">
	import type { Snippet } from 'svelte';

	interface LayoutProps {
		children: Snippet;
	}

	const { children } = $props() as LayoutProps;
</script>

{@render children()}

Once this is fixed and the types generated by Svelte are used then this workaround should be removed.

<script lang="ts">
	const { children } = $props();
</script>

{@render children()}

@CollierCZ
Copy link

If I do the workaround, I get Typescript errors. The types Svelte generates (visible if you run svelte-package are all like this:

props: Record<string, never>;

That causes errors like this (seen through svelte-check):

Type 'boolean' is not assignable to type 'never'.ts(2322)

Props have the right types if I don't use runes or don't assert types.

@ota-meshi ota-meshi added feat: typescript feat: svelte v5 bug Something isn't working and removed bug Something isn't working labels Sep 13, 2024
@ota-meshi
Copy link
Member

Thank you for posting this issue!

Hmm. It seems like a bug but the rule seems to work fine since it's actually any.
I don't have any ideas yet how to work around it in this plugin 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants