Comment déclarer les types de boutiques personnalisées ?
Svelte propose de jolis concepts de magasins faciles à utiliser. L’un d’eux est « magasins personnalisés” qui rend pratique l’obscurcissement des données réactives stockées et son accès via un ensemble de fonctions personnalisées.
Par exemple, un compteur qui compte des pommes et des bananes, je peux créer une boutique personnalisée qui n’expose pas directement mes données. Au sein d’une fonction, je peux « masquer » le magasin et exposer uniquement les fonctions que je souhaite utiliser dans mes applications au lieu de les exposer publiquement set
et update
. Ceci pour éviter les erreurs de comportement et les changements inattendus, ce qui peut être vraiment utile à mesure que la base de code grandit.
import { writable } from 'svelte/store';export interface Counter {
apples: number;
bananas: number;
}
const initStore = () => {
const initialCounter: Counter = {
apples: 0,
bananas: 0
};
const { subscribe, set, update } =
writable(initialCounter);
return {
subscribe,
incBanana: () =>
update(({ bananas, ...rest }) => ({
...rest,
bananas: bananas + 1
})),
decBanana: () =>
update(({ bananas, ...rest }) => ({
...rest,
bananas: bananas - 1
})),
reset: () => set(initialCounter)
};
};
export const counter = initStore();
Au-dessus du code, l’extrait suit l’exemple de documentation de Svelte avec l’ajout d’un type — Counter
— pour l’objet enregistré dans ma boutique et quelques fonctions personnalisées — incBanana
, decBanana
et reset
.
Notez que je n’ai tout simplement pas implémenté les fonctions liées aux « pommes » pour garder l’extrait de code petit. Dans un cas d’utilisation réel, j’aurais peut-être même extrait leupdate()
partie à une fonction pour éviter le double code mais, j’ai aussi sauté cette partie car elle n’aurait pas beaucoup de valeur dans ce contexte d’article de blog.
Lors de la liaison dans un composant, cela fonctionne comme prévu.
Cependant, même si npm run dev|build|check
sont tous bien, Webstorm n’est pas en mesure de dériver les valeurs du magasin lorsqu’il est utilisé dans un TypeScript script
bloquer.
Je ne sais pas exactement s’il s’agit d’un énième problème du plugin Jetbrains Svelte ou si le store est dérivé comme any
type par le bundler (qui ignorerait le strict
option). Néanmoins, j’aime plutôt régler le problème en améliorant le type de déclaration du magasin.
Parce que ma boutique personnalisée expose mes fonctions maison mais aussi le root subscribe
, sa déclaration doit également lui fournir un support.
Par conséquent, le moyen le plus simple à mon avis est d’hériter de l’existantReadable
type de Svelte.
import {type Readable} from 'svelte/store';export interface AuthStore extends Readable<Counter> {
incBanana: () => void;
decBanana: () => void;
reset: () => void;
}
En définissant les types génériques sur mon type de données personnalisé — Counter
— Je peux indiquer quel type est manipulé dans le magasin et en déclarant mes fonctions, je peux améliorer les typages.
Je peux utiliser cette nouvelle interface pour définir le type de retour de la fonction d’initialisation — initStore
— et c’est déjà ça.
import { type Readable, writable } from 'svelte/store';export interface Counter {
apples: number;
bananas: number;
}
export interface AuthStore extends Readable<Counter> {
incBanana: () => void;
decBanana: () => void;
reset: () => void;
}
const initStore = (): AuthStore => {
const initialCounter: Counter = {
apples: 0,
bananas: 0
};
const { subscribe, set, update } =
writable(initialCounter);
return {
subscribe,
incBanana: () =>
update(({ bananas, ...rest }) => ({
...rest,
bananas: bananas + 1
})),
decBanana: () =>
update(({ bananas, ...rest }) => ({
...rest,
bananas: bananas - 1
})),
reset: () => set(initialCounter)
};
};
export const counter = initStore();
Lorsque j’ouvre mon composant, je constate que Webstorm comprend maintenant correctement le type de mes données.
Vers l’infini et au-delà
David