sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.34k stars 4.1k forks source link

Svelte 5: `$bindable()` type is unknown #12901

Open hyunbinseo opened 3 weeks ago

hyunbinseo commented 3 weeks ago

Describe the bug

Cannot get $bindable return values to be typed.

Am I missing something?

<script lang="ts">
  let {
    noTypeInfo = $bindable(),
    typeBoolean = $bindable<boolean>(),
    defaultValue = $bindable(false)
  } = $props();

  // let noTypeInfo: unknown
  // let typeBoolean: unknown
  // let defaultValue: unknown
</script>

Reproduction

Same as above.

Logs

No response

System Info

Name: Svelte for VS Code
Id: svelte.svelte-vscode
Description: Svelte language support for VS Code
Version: 108.6.0
Publisher: Svelte
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode

System:
  OS: macOS 14.6.1
  CPU: (10) arm64 Apple M1 Pro
  Memory: 61.98 MB / 16.00 GB
  Shell: 5.9 - /bin/zsh
Binaries:
  Node: 20.16.0 - ~/.local/state/fnm_multishells/56571_1724043253997/bin/node
  npm: 10.8.1 - ~/.local/state/fnm_multishells/56571_1724043253997/bin/npm
  pnpm: 9.7.0 - ~/.local/state/fnm_multishells/56571_1724043253997/bin/pnpm
Browsers:
  Chrome: 127.0.6533.120
  Edge: 127.0.2651.105
  Safari: 17.6
npmPackages:
  svelte: 5.0.0-next.225 => 5.0.0-next.225

Severity

annoyance

hyunbinseo commented 3 weeks ago

I am not sure if this issue belongs in the language-tools repo.

I cannot get $props().children to be typed, and it was raised over there.

<script>
  // let children: unknown
  let { children } = $props();
</script>

<!-- 'children' is of type 'unknown'.js(18046) -->
{@render children()}
jasonlyu123 commented 3 weeks ago

To type the prop you need to type the props object and not individual props.

https://svelte-5-preview.vercel.app/docs/runes#$props

The unknown part is generated by language-tools. But without that, it will still be inferred as any. Not sure if it makes sense to allow it since it isn't how typescript inferred the type for destructuring.

hyunbinseo commented 3 weeks ago

So I guess there is no special return type for $bindable? Is this good?

<script lang="ts">
  type Props = { b: boolean };
  let { b = $bindable<boolean>() }: Props = $props();
</script>

Wished this was documented in the $bindable preview documentation.


I know TypeScript object must be typed as a whole, but still:

  1. If default values are provided, manual typing might not be necessary:
<script lang="ts">
  let {
    // Only this prop needs typing,
    // but the whole Props should be typed.
    showModal = $bindable<boolean>(),
    closeWithBackdropClick = false,
    onclose = (() => {}) as () => unknown
  } = $props();
</script>
  1. props and the Props type can mismatch:
<!-- src/lib/Component.svelte -->
<script lang="ts">
  // Even-though the fallback value has been provided,
  let { b = $bindable(false) }: Props = $props();

  // Since it is not a optional key in the Props type:
  type Props = { b: boolean };
</script>
<!-- src/routes/+page.svelte -->
<script>
  import Component from '$lib/Component.svelte';
</script>

<!-- Property 'b' is missing in type '{}' but required in type 'Props'. -->
<Component></Component>