svelte icon indicating copy to clipboard operation
svelte copied to clipboard

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

Open hyunbinseo opened this issue 1 year ago • 3 comments

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 avatar Aug 19 '24 05:08 hyunbinseo

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.

  • https://github.com/sveltejs/language-tools/issues/2466
<script>
  // let children: unknown
  let { children } = $props();
</script>

<!-- 'children' is of type 'unknown'.js(18046) -->
{@render children()}

hyunbinseo avatar Aug 19 '24 05:08 hyunbinseo

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.

jasonlyu123 avatar Aug 19 '24 05:08 jasonlyu123

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>

hyunbinseo avatar Aug 19 '24 05:08 hyunbinseo