Bind radio group to a boolean value using svelte

Viewed 953

I want to create a svelte component that exports a boolean value that can be binded and represents the state of a radio button group, like the following code:

<script lang="ts">
    export let firstSelected = true;
</script>

<input type="radio" bind:group={firstSelected} value={true}/>
<input type="radio" bind:group={firstSelected} value={false}/>

The problem with this is that svelte-check issues the errors:

Error: Type 'true' is not assignable to type 'string | number | string[]'. (ts)
Error: Type 'false' is not assignable to type 'string | number | string[]'. (ts)

A possible fix is to use a number instead of a boolean, however this changes the interface of the component:

<script lang="ts">
    export let firstSelected = 1;
</script>

<input type="radio" bind:group={firstSelected} value={1}/>
<input type="radio" bind:group={firstSelected} value={0}/>

Is there a way to fix this while still exposing a bindable boolean value? If not, is there a way to ignore this error?

REPL with example: https://svelte.dev/repl/b6e9042a1b594f2bb77b1e8e7b38ffe1?version=3.31.2

4 Answers

This was an overly strict typing of the Svelte tooling, which is relaxed in the latest version of Svelte for VS Code (105.9.0) and svelte-check (2.2.12).

Using another number variable together with a reactivity declaration and a on:change handler fixes the problem:

<script lang="ts">
    export let firstSelected = true;
    
    $: _firstSelected = Number(firstSelected);
    
    function handleChange(e) {
        firstSelected = Boolean(_firstSelected);
    }
</script>

<input type="radio" bind:group={_firstSelected} value={1} on:change={handleChange}/>
<input type="radio" bind:group={_firstSelected} value={0} on:change={handleChange}/>

REPL

You can use a number, like:

<script lang="ts">
    export let firstSelected = true;
    
    let group
    
    $: group = firstSelected ? 1 : 0
</script>

<input type="radio" bind:group={group} value={1}/>
<input type="radio" bind:group={group} value={0}/>

There is a bug here for sure, as the binding does not cast to a boolean. As a quick fix: Check the code below

<input type="checkbox" on:change="{myvar = (myvar === true) ? false : true}">
Related