【问题标题】:Svelte Components as Object PropertiesSvelte 组件作为对象属性
【发布时间】:2021-05-26 01:00:35
【问题描述】:

我想接受一个组件作为道具。

import AComponent from './AComponent.svelte';

type MyType = {
  [key: string]: any; // just an example
}

type IWantToAcceptAComponent<T> = {
  component: SvelteComponentTyped<{ record: T }>;
}

const componentPropObject: IWantToAcceptAComponent<MyType> = {
  component: AComponent // error here
}
Error: Type 'typeof AComponent__SvelteComponent_' is missing the following properties from type 
'SvelteComponentTyped<{ record: MyType; }>': $set, $on, $destroy, $$prop_def, and 5 
more.ts(2740)

我认为 typedef 应该是:

type IWantToAcceptAComponent<T> = {
  component: typeof SvelteComponentTyped<{ record: T }>;
}

但这会导致更奇怪的错误。

这种类型是显式的,这一点相当重要,因为它应该是用户导出界面的一部分。

【问题讨论】:

  • 据我所知,将组件作为道具传递并不是一个好主意
  • 为什么要将组件作为道具传递
  • 主要是因为该组件非常基于数据,我可以保持所有相关类型的唯一方法,嗯,相关的,是通过我传递的道具的类型来管理这种关系。此外,说将组件作为道具(或至少是对象的一部分)传递是一个坏主意是一种谬论......它确实在 Svelte 快速入门中! svelte.dev/tutorial/svelte-component

标签: typescript svelte typescript-generics


【解决方案1】:

您需要调整IWantToAcceptAComponent 的输入。您不能直接使用SvelteComponentTyped,因为这意味着您需要实例类型,而不是构造函数类型。但是你也不能这样做 typeof SvelteComponentType&lt;..some generic&gt; 因为这是 TypeScript 的语法错误。您需要像这样键入“接受返回特定实例的类构造函数”:

type IWantToAcceptAComponent<T> = {
  component: new (...args: any) => SvelteComponentTyped<{ record: T }>;
}

请注意,您需要 Svelte for VS Code 版本 105 或更高版本以及(如果您使用它)svelte-check 2.0.0 或更高版本才能正常工作。之前的类型略有不匹配。

如果你想使用 TypeScript 文件中的代码,你需要激活 Svelte for VS Code 扩展的 TypeScript 插件。否则,所有 Svelte 导入都被键入为通用 SvelteComponentDev,而没有正确的类型。

【讨论】:

  • 你是救命稻草——我以为我早点回复过这个!非常感谢帮忙。解决了这个问题!
  • 呸,我说得太早了——看起来好像奏效了,但事实并非如此。我现在收到此错误:Type 'typeof SvelteComponentDev' is notassignable to type 'new (...args: any) => SvelteComponentTyped; },任何,任何>'。有什么想法吗?
  • 我怀疑您想使用 TS 文件中的代码。我相应地更新了我的答案。一般来说,TS/Svelte 文件互操作很棘手,有时不能完全匹配,您需要 TS 插件才能获得更好的互操作。
【解决方案2】:

尽管我不使用打字稿,但我看不出有什么理由可以使用纯 JS 而不是 TS。 我制作了REPL,它基本上包含了作为道具传递的另外两个“子组件”。

结构类似于:

App.svelte

<script>
  //App.svelte
  import A from "./A.svelte";
  import B from "./B.svelte";
  import Wrapper from "./Wrapper.svelte";

  let props = [  { component: A }, { component: B } ];
</script>

<Wrapper {props} />

Wrapper.svelte:

<script>
    //Wrapper.svelte
    export let props = [];
</script>

{#each props as prop}
    <p>
        <svelte:component this={prop.component} />
    </p>
{/each}

A.svelte:

   <!-- A.svelte -->
   <h2>COMP A</h2>

B.svelte:

    <!-- B.svelte -->    
    <h3>COMP B</h3>

【讨论】:

  • 你说得对——有可能!问题是关于使其成为强类型所需的类型。如果我只是将类型定义更改为组件:任何,一切都很好。但我更喜欢强类型。
猜你喜欢
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 2021-11-15
  • 2022-11-02
  • 1970-01-01
  • 2015-11-12
  • 2011-08-24
  • 1970-01-01
相关资源
最近更新 更多