作为对象属性的 Svelte 组件

nyx*_*nyx 5 typescript typescript-generics svelte

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

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
}
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)

我认为 typedef 可能应该是:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

dum*_*umm 5

您需要调整您的输入IWantToAcceptAComponent。您不能SvelteComponentTyped直接使用,因为这意味着您需要实例类型,而不是构造函数类型。但你也不能这样做,typeof SvelteComponentType<..some generic>因为这是 TypeScript 的语法错误。您需要使用 Svelte 提供的ComponentType接口输入“接受返回特定实例的类构造函数”,如下所示:

import type { ComponentType, SvelteComponentTyped } from 'svelte';

type IWantToAcceptAComponent<T> = {
  component: ComponentType<SvelteComponentTyped<{ record: T }>>;
  // If you're on and old Svelte version which doesn't provide ComponentType yet:
  componentAlternative: new (...args: any) => SvelteComponentTyped<{ record: T }>;
}
Run Code Online (Sandbox Code Playgroud)

请注意,您需要 Svelte for VS Code 版本 105 或更高版本以及(如果您使用它)svelte-check2.0.0 或更高版本才能正常工作。之前的打字有点不匹配。

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


小智 0

尽管我不使用 typescript,但我看不出为什么纯 JS 可以做到这一点,而 TS 却不行。我制作了REPL,它基本上包装了作为 props 传递的另外两个“子组件”。

结构是这样的:

应用程序.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} />
Run Code Online (Sandbox Code Playgroud)

包装器.svelte :

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

{#each props as prop}
    <p>
        <svelte:component this={prop.component} />
    </p>
{/each}
Run Code Online (Sandbox Code Playgroud)

A.svelte:

   <!-- A.svelte -->
   <h2>COMP A</h2>
Run Code Online (Sandbox Code Playgroud)

B.svelte:

    <!-- B.svelte -->    
    <h3>COMP B</h3>
Run Code Online (Sandbox Code Playgroud)