Is your feature request related to a problem? Please describe.
The TypeScript preprocessor does not yet fully support reactive statements, which makes it difficult to use TypeScript with Svelte.
There's an open question of how Svelte's syntax should be included in TypeScript. This is essentially a new syntax that needs to be spec'd out.
Describe the solution you'd like
It would be natural to do something like:
$: let squared: number = num * num;
$: let cubed: number = squared * num;
However, Svelte does not support let in reactive statements today.
Describe alternatives you've considered
Potentially we could find the first time a reactive variable used in the preprocessor and insert the let before passing it to TypeScript. However, this is sort of against the spirit of TypeScript, which expects some extra verbosity from the user in exchange for extra error checking such as checking whether you're referencing an undeclared variable.
I see no harm in allowing regular JS users to do:
$: let squared = num * num;
$: let cubed = squared * num;
How important is this feature to you?
TypeScript support in general is very important to myself and the community. Whether this is the best way to implement support or not is TBD.
Additional context
I think that the Svelte team should weigh in here on how we want this to work even if it's not this syntax. It doesn't seem right to me that the preprocessor would be in charge of deciding because then you could end up with a different syntax in each preprocessor and language-tools/VSCode might not know how to handle the syntax.
I believe that the preprocessor doesn't currently use the AST or do anything sophisticated and that the Svelte compiler is already tracking whether a variable usage is the first and should be a declaration or not. As a result, it would probably be easiest to implement in the Svelte compiler (for someone familiar with the Svelte compiler code. For someone new to the codebase that's probably flipped because the Svelte codebase is larger and more complicated in general.)
label: let is invalid javascript
Yeah, but Svelte isn't interpreted as JavaScript, but rather compiled to JavaScript and then interpreted, right?
Svelte being very close to JS makes other tooling work easily with it. If you add too much non-standard things you'll likely run into problems.
The only tooling I'm aware of are the preprocessors and language-tools and I'm specifically proposing this to make it easier for that tooling to deal with in this case. Is there other tooling I might be overlooking?
I'm totally open to suggestions though on what the preferred syntax for reactive variables in TypeScript should be if you have ideas
Having the <script> tag be at least parseable as normal javascript is currently one of the non-negotiable aspects of Svelte's syntax. We don't have the resources to maintain a fork of Acorn or to support this in all of the different tooling and syntax highlighting and so on. If non-JS syntax was allowed in script tags, I'd probably bail on maintaining the official ESLint plugin, for example.
i believe it still has to be valid JavaScript, it just gets compiled to different JavaScript, for example to give labelled statements different behaviour
svelte uses an ESTree compliant parser, so i don't think this would be possible to do, or at least it would require a lot of changes (probably a custom parser?). you'll probably need to come up with a valid JS syntax that's as obscure as labelled statements to use for this
Ahh, okay. I didn't think about it from the parsing angle. That's super helpful. Thanks! It sounds like it would be much better to handle in the preprocessor in this case.
I'm not quite sure what they best syntax is here. There's something we have to invent for the intersection of Svelte and TypeScript.
Without let, but with typing, would be most similar to Svelte:
$: squared: number = num * num;
$: cubed: number = squared * num;
Having or allowing users to use let would be most similar to TypeScript and thus easiest to implement in the preprocessor since we're passing it to TypeScript first:
$: let squared: number = num * num;
$: let cubed: number = squared * num;
Neither would be valid TypeScript, JS, nor Svelte, but there's not much syntax that would be when you have both Svelte and TypeScript in the mix.
I'm still curious what you all think even if we're implementing purely in the pre-processor because I don't want to go off and invent our own non-blessed syntax more than necessary.
let squared: number;
$: squared = num * num;
That could be an option. I do like that we wouldn't be having to come up with additional syntax in that case. Though it is more verbose to have to split declaration and initialization into two separate lines. I think the biggest drawback is that it's somewhat unexpected by users to need two lines in this scenario.
Regardless of which route we go with, we should document it somewhere since there's nowhere that explains it yet. The TypeScript question in the FAQ would be one place we could put it. I think this is the only syntax that really needs any explanation since it's the only place where Svelte does something you wouldn't normally do in Vanilla JS or TypeScript.
There was already similar discussion regarding TypeScript syntax in the https://github.com/sveltejs/svelte/issues/4518 .
Thanks for the pointer!
Most helpful comment
label: letis invalid javascript