Typescript + Svelte - Hur man lägger till typer till spridda komponentprop
Är det möjligt att säkerställa typ-säkerhet med komponenter som är sammansatta av andra?
t.ex. om jag vill bygga en speciell typ av inmatning med viss validering, etc som bör utöka min basinmatning.
BaseInput.svelte
<script lang="ts">
export let value = '';
// + a lot more props
</script>
<input bind:value ... />
AgeInput.svelte - detta utökar BaseInput
<script lang="ts">
import BaseInput from './BaseInput.svelte'
export let {...inputProps}: /* Can we spread and infer BaseInput props? */;
</script>
<BaseInput {...inputProps} type="number" />
Kan vi härleda BaseInput-egenskaperna?
Svar #1
Svelte bygger inputtypen number annorlunda än typen text.
För min del byggde jag två typer av inmatningar att importera.
För inputText.svelte:
<script lang="ts">
export enum TextType { text = "text", email = "email", password = "password" }
export let id: string;
export let type: TextType;
export let label: string | null = null;
export let placeholder: string | null = null;
export let value: string | null = null;
function typeAction(node: HTMLInputElement) {
node.type = type
}
</script>
<div class="textInput">
<label class="textLabel" for={id}>{label}</label>
<input on:input bind:value id={id} type="text" placeholder={ placeholder } use:typeAction />
</div>
Den här funktionen:
function typeAction(node: HTMLInputElement) {
node.type = type
är mycket viktigt att passera typ av inmatning:
export enum TextType { text = "text", email = "email", password = "password" }
Och här är ett exempel på min inputNumber.svelte :
<script lang="ts">
export let id: string;
export let label: string | null = null;
export let placeholder: string | null = null;
export let value: number | null = null;
export let min: number | null = null;
export let max: number | null = null;
</script>
<div class="numberInput">
<label class="numberLabel" for={id}>{label}</label>
<input on:change bind:value id={id} type="number" placeholder={placeholder} min = {min} max = {max} {...$$restProps}/>
</div>
Efter att jag importerar det som vanligt.
Svar #2
Du kan använda $$props-variabeln i Svelte.
app.svelte
<script>
import AgeInput from './AgeInput.svelte'
</script>
<AgeInput
bi_p1="base input prop 1"
bi_p2="base input prop 2"
ai_p1="age input prop 1"
ai_p2="age input prop 2"
/>
baseinput.svelte
<script lang="ts">
export let bi_p1;
export let bi_p2;
// + a lot more props
</script>
<input />
<pre>
base input properties
bi_p1: {bi_p1}
bi_p2: {bi_p2}
</pre>
ageinput.svelte
<script lang="ts">
import BaseInput from './BaseInput.svelte';
const {bi_p1, bi_p2, ai_p1, ai_p2, ...restProps} = $$props
</script>
<BaseInput {bi_p1} {bi_p2} type="number" />
<pre>
age input props
ai_p1: {ai_p1}
ai_p2: {ai_p2}
</pre>
Här är REPL-länken https://svelte.dev/repl/a22f404887164fc4a5a6d54dfdff1380?version=3.17.2
