-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
The use of unique symbol as the type of SnippetReturn means that every instance refers to a unique symbol. They are not structurally compatible with each other (unlike basically everything else in typescript)
As such, you have to use typeof on them to get a reference to the same unique symbol.
Which svelte does. Or tries to.
Unfortunately, however, it contains two different instances of the SnippetReturn symbol - one in src/index.d.ts, and one in types/index.d.ts.
Both contain const SnippetReturn: unique symbol (of some form), which means both create different unique symbols
In turn, the Snippet types that exist in each file now have different return values, even though they are typeof'ing that symbol, and because of how unique symbols work, those return values are incompatible with each other.
This causes issues that pop up occasionally on the issue tracker such as #13670.
The above is the cause of this issue (and a few others).
The solution, AFAIK, is to share the typeof (unique symbol) between both files, by placing it in a third, so there is only one unique symbol.
(I say typeof because as per above, only the typeof will give you the same reference to the unique symbol, so you can't just share the unique symbol, you have to share the typeof)
Reproduction
Just to remove svelte components entirely, i'll use a .ts file repro.
Place the following in a .ts file in a svelte project (obviously, modify the node_modules path to be correct for your project).
import type { Snippet as SrcSnippet } from '../../../node_modules/svelte/src/index.d.ts';
import type { Snippet } from 'svelte';
let foo: SrcSnippet;
let bar: Snippet;
foo = bar;You will receive the following error:
✗ bun run check
$ svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
====================================
Loading svelte-check in workspace: /Users/dannyb/sources/modeler-svelteflow
Getting Svelte diagnostics...
/Users/dannyb/sources/modeler-svelteflow/src/components/SearchableTreeView/foo.ts:7:1
Error: Type 'import("svelte").Snippet<[]>' is not assignable to type 'import("/Users/dannyb/sources/modeler-svelteflow/node_modules/svelte/src/index").Snippet<[]>'.
Type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & typeof SnippetReturn' is not assignable to type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & typeof SnippetReturn'. Two different types with this name exist, but they are unrelated.
Type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & unique symbol' is not assignable to type 'unique symbol'.
foo = bar;
It is correct - the types are in fact unrelated. The strings about @render are a red herring they are just part of the type name in the file.
The complaint that the different unique symbols aren't compatible is the real complaint.
Now, i will say, while it is easy to reproduce a failure and show it's broken - it is hard to track down the exact circumstances under which both end up getting into the picture.
But it's definitely the same failure in the real world (and in the issues i can find on the issue tracker).
In the real world I have a failing treeview where the render is in a child component (treeitem), the snippet is in the parent component (treeview), and the typecheck failure is in the parent - this is the output of svelte check:
Svelte: Type '(label: string, query: string) => ReturnType<import("svelte").Snippet>' is not assignable to type 'Snippet<[string, string]>'.
Type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & typeof SnippetReturn' is not assignable to type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & typeof SnippetReturn'. Two different types with this name exist, but they are unrelated.
Type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & unique symbol' is not assignable to type 'unique symbol'.
If i remove the snippet related declarations from types/index.d.ts, it causes the typecheck failure to go away. So they are definitely getting imported into the language server, and svelte check.
In any case, all of this is somewhat moot - i'm just recording it in case it's ever useful for some other bug later. It should hopefully be obvious this is broken, and there is a hopefully easy fix the overall issue - share the typeof <unique symbol> between the two files so they are the same unique symbol.
I also am going to go over to the typescript repo and file a bug that they should give the unique symbols context info or something in the error messages - so that it is obvious they are not the same.
Logs
System Info
Not relevantSeverity
annoyance