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

Unexpected Error when Destructing $store Values #444

Closed
JoeDailey opened this issue Aug 11, 2020 · 6 comments
Closed

Unexpected Error when Destructing $store Values #444

JoeDailey opened this issue Aug 11, 2020 · 6 comments
Labels
bug Something isn't working Fixed Fixed in master branch. Pending production release.

Comments

@JoeDailey
Copy link

JoeDailey commented Aug 11, 2020

Describe the bug
The statement $: ({ value } = $store); is valid syntax when value is a property of $store and $store is a Svelte store. It behaves like normal destructuring and is reactive to store updates. This produces an error when lang="ts".

# App.svelte
------------
<script lang="ts">
  import data from "./store";
  $: ({ count } = $data);
</script>
jd:/svelte-playground $ yarn svelte-check                                                                                                                                                                                                                      [0:30]
yarn run v1.22.4
warning package.json: No license field
$ /home/jd/Projects/svelte-playground/node_modules/.bin/svelte-check

Loading svelte-check in workspace: /home/jd/Projects/svelte-playground
Getting Svelte diagnostics...
====================================

/home/jd/Projects/svelte-playground/src/App.svelte:3:9
Error: No value exists in scope for the shorthand property 'count'. Either declare one or provide an initializer. (ts)
;
  $: ({ count } = $data

====================================
svelte-check found 1 error and 0 warnings
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

To Reproduce

  1. Start with this REPL: link
  2. Download it and add TS support to the project: link
  3. Modify App.svelte by adding lang="ts" to the opening <script> tag. (see the above snippet)
  4. run svelte-check

Expected behavior
This is valid Svelte/JS syntax and his code runs fine. It should not produce typechecker errors.

Screenshots
If applicable, add screenshots to help explain your problem.
image

System (please complete the following information):

  • OS: Windows
  • IDE: VSCode (Windows-Linux Subsystem)
  • Plugin/Package:
    • Svelte for VSCode
    • svelte-check
    • @tsconfig/svelte
@JoeDailey JoeDailey added the bug Something isn't working label Aug 11, 2020
@JoeDailey
Copy link
Author

JoeDailey commented Aug 11, 2020

Workaround
Don't use destructuring on Svelte stores in Typescript. This is not ideal but not a blocker. It is just less concise when destructuring several properties at once.
REPL: link

# App.svelte
------------
<script lang="ts">
  import data from "./store";
  $: count = $data;
</script>

Of course you can always just refer to the store value directly in the DOM to see reactive updates.

@dummdidumm
Copy link
Member

From input

<script lang="ts">
  import data from "./store";
  $: ({ count } = $data);
</script>

<main>
  <h1>Count (inline): {$data.count}</h1>
  <h1>Count (reactive destructure): {count}</h1>
	<button on:click={() => data.update(c => ({count: c.count + 1}))}>
    Increment
  </button>
</main>

svelte2tsx generates the output:

<></>;
import data from "./store";
function render() {

  
  ;() => {$: ({ count } = __sveltets_store_get(data));}
;
() => (<>

<main>
  <h1>Count (inline): {__sveltets_store_get(data).count}</h1>
  <h1>Count (reactive destructure): {count}</h1>
	<button onclick={() => data.update(c => ({count: c.count + 1}))}>
    Increment
  </button>
</main> </>);
return { props: {}, slots: {}, getters: {}, events: {} }}

export default class extends createSvelte2TsxComponent(__sveltets_partial(render)) {
}

The problem is that the $-assignment is wrapped in a function, so the value does not exist outside of its scope.

@JoeDailey JoeDailey changed the title Unexpected Error when Destructing $store vValues Unexpected Error when Destructing $store Values Aug 11, 2020
@jasonlyu123
Copy link
Member

we might have to check how the svelte compiler determine when it should declare a variable see if we miss other situation

@dummdidumm
Copy link
Member

dummdidumm commented Aug 11, 2020

The problem is the ts AST analysis. It only does the let x = ... transformation if it's a binary expression, but in this case it's a binary expression wrapped inside a parenthized expression.

Edit: I'm in the middle of fixing this - all these if-then-also-think-of-this-corner-case-checks make my mind blurry 😄

@jasonlyu123
Copy link
Member

jasonlyu123 commented Aug 11, 2020

I think the left check also needs to be changed

ts.isIdentifier(node.statement.expression.left)

https://github.com/sveltejs/svelte/blob/f739b4772a4ad32c0fd337afb9d5594ebd776073/src/compiler/compile/Component.ts#L607

@dummdidumm
Copy link
Member

Yes, multiple things need to be changed. I'll create a draft PR so you can see my current state.

dummdidumm pushed a commit to dummdidumm/language-tools that referenced this issue Aug 11, 2020
dummdidumm added a commit that referenced this issue Aug 15, 2020
* (fix) destructuring inside $

#444

* closer to a solution

* remove ';' insertion

* comment

* support case where user defines some of the destructured variables

* add ast extract identifiers util

* support array destructuring

* do all transformations in the end
@dummdidumm dummdidumm added the Fixed Fixed in master branch. Pending production release. label Aug 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Fixed Fixed in master branch. Pending production release.
Projects
None yet
Development

No branches or pull requests

3 participants