Reputation: 677
I have a svelte component that receives two props: value
and multiple
. multiple
has boolean
type, and value
's type depends on whether multiple
is true
or false
. If I used these props in a function I would do something like:
interface Single {
multiple: false;
value: string | null
};
interface Multiple {
multiple: true;
value: string[] | [];
};
const doSomenthing = (props: Single | Multiple) => {};
Typescript would complain if I try to call the function with:
doSomething({ multiple: false, value: ['hello', 'world'] })
So far, I haven't figured the way of doing the same thing on svelte, so that if I instantiate the component:
<MyComponent multiple={false} value={['hello', 'world']} />
throws an error.
Upvotes: 0
Views: 1190
Reputation: 185225
In this case you can use one generic parameter for multiple
to make value dependent on it:
<script lang="ts" generics="T extends boolean">
export let multiple: T;
export let value: T extends true ? string[] : string;
</script>
(Note that generics syntax is not finalized. RFC - Feedback thread)
Unfortunately {#if multiple}
will currently not narrow the type of value
correctly. So maybe it would be better to just drop multiple
altogether and just use Array.isArray(value)
in its place.
<script lang="ts">
export let value: string[] | string;
</script>
{#if Array.isArray(value)}
{value.join(', ')}
{:else}
{value}
{/if}
Upvotes: 0
Reputation: 7721
I see you're asking for setting the props seperately
<MyComponent multiple={false} value={['hello', 'world']} />
but why not export one prop and use ComponentProps to check for the correct type - REPL
<script lang="ts">
interface Single {
multiple: false;
value: string | null;
}
interface Multiple {
multiple: true;
value: string[] | [];
}
export let singleOrMultiple: Single | Multiple;
</script>
Comp - {singleOrMultiple.multiple} {singleOrMultiple.value}
<script lang="ts">
import Comp from '$lib/Comp.svelte';
import type { ComponentProps } from 'svelte';
const props: ComponentProps<Comp> = {
singleOrMultiple: { multiple: false, value: null }
};
</script>
<Comp {...props} />
Upvotes: 0
Reputation: 16451
The only thing I can come up with is to type the $$Props
generally, note that you would still have to type the exports individually with all possibilities as well. Meaning this is not perfect either because internally the type of value can be all four.
<script lang="ts">
type Multiple = { multiple: true; value: string[] | [] };
type Single = { multiple: false; value: string | null };
type $$Props = Multiple | Single;
export let multiple: boolean;
export let value: string | string[] | [] | null;
</script>
{#if multiple}
{#each value as item}a{/each}
{:else}
{#each value as item}a{/each}
{/if}
the above code will give errors when using the component wrong as you requested, but it will also give errors on the #each
block because null
is not an iterable.
Upvotes: 0