svelte
svelte copied to clipboard
Svelte 5: `$bindable()` type is unknown
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
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()}
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.
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:
- 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>
- 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>