简体   繁体   English

当我通过 setContext 或组件道具传递存储时,如何为自定义存储设置类型?

[英]How do I set the type, for custom store, when I pass store via setContext or component prop?

When using SvelteKit, the store must always be created in the route page / layout , otherwise there will be problems with the status being up-to-date after refreshing.使用 SvelteKit 时,必须始终在 route page / layout中创建store ,否则会出现刷新后状态为 up-to-date 的问题。
You can't create a store in an imported module, because the server-side module only loads once, and this causes errors in the store .您不能在导入的模块中创建store ,因为服务器端模块只加载一次,这会导致store错误。
All this leads to a certain situation with types.所有这些都导致了类型的某种情况。

The problem:问题:

I create and pass the store from +page.svelte to Child.svelte , via setContext :我通过setContext创建并将商店从+page.svelteChild.svelte


<!-- +page.svelte -->
<script>
  import Child from "./Child.svelte";
  import { writable } from 'svelte/store';
  import { setContext } from "svelte";
  
  function createCount() {
    /** @type {import("svelte/store").Writable<number>} */
    const { subscribe, set, update } = writable(0);
    
    return {
      subscribe,
      increment: () => update(n => n + 1),
      decrement: () => update(n => n - 1),
      reset: () => set(0)
    };
  }
  
  export const count = createCount();
  
  setContext("store", count);
</script>

<Child/>
<!-- Child.svelte -->
<script>
import { getContext } from "svelte";
  
  const count = getContext("store");
</script>

<h1>The count is {$count}</h1>

<button on:click={count.increment}>+</button>
<button on:click={count.decrement}>-</button>
<button on:click={count.reset}>reset</button>

In Child.svelte the type for store count is any :Child.svelte中, store计数的类型是any
奥布拉兹

And it should be as in the place of the declaration:它应该在声明的位置:
奥布拉兹

That's what it should be the type of store , returned from getContext("store"):这应该是store的类型,从 getContext("store") 返回:

const count: {
    subscribe: (this: void, run: Subscriber<number>, invalidate?: Invalidator<number> | undefined) => Unsubscriber;
    increment: () => void;
    decrement: () => void;
    reset: () => void;
}

Passing via <Child {count}/> has the same problem.通过<Child {count}/>传递有同样的问题。
奥布拉兹

QUESTION: How can this be done?问题:如何做到这一点?

Alternative选择

It doesn't.它没有。 You can only create a store in a module, and import it - then the types are preserved.您只能在模块中创建store并导入它 - 然后类型被保留。
But this creates some problems with store validity, as I wrote about at the beginning.但这会在store有效性方面产生一些问题,正如我在开头所写的那样。

There are two primary options: Use preprocess-svelte and write TypeScript or add JSDoc type annotations.有两个主要选项:使用preprocess-svelte并编写 TypeScript 或添加 JSDoc 类型注释。

With TS:使用 TS:

<script lang="ts">
    import { getContext } from 'svelte';

    // Prop
    export let count: StoreType;

    // Context
    const store = getContext<StoreType>('context');
</script>

With JSDoc:使用 JSDoc:

<script>
    import { getContext } from 'svelte';

    // Prop
    /** @type {StoreType} */
    export let count;

    // Context
    /** @type {StoreType} */
    const store = getContext('context');
</script>

You can declare types in separate .d.ts files or use @typedef .您可以在单独的.d.ts文件中声明类型或使用@typedef


The createCount function can be extracted to a separate file without issue. createCount function 可以毫无问题地提取到单独的文件中。 That way its return type can also be used when typing props/contexts.这样,在输入道具/上下文时也可以使用它的返回类型。 Eg例如

// create-count.js
import { writable } from 'svelte/store';

export function createCount() {
    const { subscribe, set, update } = writable(0);

    return {
        subscribe,
        increment: () => update(n => n + 1),
        decrement: () => update(n => n - 1),
        reset: () => set(0),
    };
}
<script>
    import { getContext } from 'svelte';

    /** @type {ReturnType<import('./create-count').createCount>} */
    export let count;

    /** @type {ReturnType<import('./create-count').createCount>} */
    const store = getContext('context');
</script>

In TS this is cleaner, since you can just import the type as part of regular code and use type aliases.在 TS 中这更简洁,因为您可以将类型作为常规代码的一部分导入并使用类型别名。

<script lang="ts">
    import type { createCount } from './create-count';
    import { getContext } from 'svelte';

    export let count: Count;

    const store = getContext<Count>('context');

    type Count = ReturnType<typeof createCount>;
</script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 React 和 Typescript 中将组件作为道具传递? - How do I pass a component as a prop in React and Typescript? 如何仅将一种商店类型传递给组件(当商店是联合类型时) - How to pass only one store type to a component (when the store is a union type) 如何为React props定义TypeScript类型,只有在将prop A传递给组件时,才会接受prop B? - How do I define a TypeScript type for React props where prop B is only accepted if prop A is passed to a component? TypeScript 错误 7053 - 创建一个使用 prop 覆盖样式的自定义 React 组件,我如何正确告诉 TS 类型是什么? - TypeScript Error 7053 - Creating a custom React component that overrides styles with a prop, how do I properly tell TS what the type is? Typescript/Vue - 当我为道具声明默认对象时,如何访问 vuex 存储? - Typescript/Vue - How can I get access to the vuex store when I'm declaring a default object for a prop? 如何指定一个道具的类型来引用另一个道具的类型? - How do I specify the type of a prop to refer to the type of another prop? 如何使用 aurelia 存储更新单个组件? - How do I update an individual component using aurelia store? 如何将 v-form 中的数据存储到 data 道具中? - How do I store data from v-form into the data prop? 如果另一个道具是指定类型,我如何使道具可选? - How do I make a prop optional if another prop is of a specified type? 如何将随机道具从 api 传递给另一个组件? - How can I pass random prop from api to another component?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM