typescript - Svelte (Vite) + Bootstrap 5 + SvelteStrap eroare: Tipul 'string' nu poate fi atribuit tipului 'ButtonColor'


Folosesc Svelte (Vite) + Bootstrap 5 + SvelteStrap. Codul meu este următorul:

<head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email /dist/css/bootstrap.min.css">
</head>
<script>
    import { Button } from 'sveltestrap';
    let color = "danger";
</script>

<div>
    <Button color="{color}">{color}</Button>
</div>

Acest lucru funcționează în mod normal în browser, dar VSCode spune:

Tipul 'string' nu poate fi atribuit tipului 'ButtonColor'.

Abia încep cu Svelte și încerc să modific exemplul standard de pe site-ul SvelteStrap:

<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email /dist/css/bootstrap.min.css">
</head>
<script lang="ts">
  import { Button } from 'sveltestrap';
  const colors: any = [
    'primary',
    'secondary',
    'success',
    'danger',
    'warning',
    'info',
    'light',
    'dark'
  ];
</script>

{#each colors as color}
  <div>
    <Button {color}>{color}</Button>
  </div>
{/each}

Folosind exemplul standard, nu apar erori. Ce greșesc? De ce se întâmplă asta?

Răspuns #1

Aceasta este o problemă de tastare, eroarea este generată de TypeScript.

Tipul așteptat al proprietății color este un tip union din diverse valori de tip string, dar în mod implicit un array de literale de tip string va fi tipizat doar ca string[], astfel încât elementele sale nu vor mai fi atribuite unui tip mai specific bazat pe literale de tip string.

Ar trebui să poți folosi as const aici pentru a restricționa tipul array-ului să fie bazat pe literali:

const colors = [
    'primary',
    'secondary',
    'success',
    'danger',
    'warning',
    'info',
    'light',
    'dark'
] as const; // <--

Aceasta este definiția completă a tipului ButtonColor:

declare type ButtonColor =
  | 'primary'
  | 'secondary'
  | 'success'
  | 'danger'
  | 'warning'
  | 'info'
  | 'light'
  | 'dark'
  | 'link';

Tipul nu este exportat (deși ar trebui să fie), așa că nu poate fi folosit direct, dar îl poți extrage din clasa Button:

import type { SvelteComponentTyped } from 'svelte';
import type { Button } from 'sveltestrap';

type PropsOf<C> = C extends SvelteComponentTyped<infer Props> ? Props : never;
type ButtonProps = PropsOf<Button>;
type ButtonColor = Exclude<ButtonProps['color'], undefined>;

Demo TS Playground

Ai putea să-ți scrii și tu array-ul folosind asta:

const colors: ButtonColor[] = [
    'primary',
    'secondary',
    'success',
    'danger',
    'warning',
    'info',
    'light',
    'dark'
];