精简的强类型组件类

问题描述 投票:0回答:2

我正在开发一个组件库,该库在组件的分组方式上有一些变化。我将组件分组为类,以便最终用户更轻松地使用该库。他们不会记住哪些名为

slots
可用,而是使用点符号访问自定义插槽。例如,
Card
组件可以具有
Header
Body
Footer
。在我的图书馆中,我想像这样使用这些组件:

<Card>
  <Card.Header>I am a Header</Card.Header>
  <Card.Body>I am a Body</Card.Body>
  <Card.Footer>I am a Footer</Card.Footer>
</Card>

我目前正在使用此功能,但我也在尝试将其强类型化,这就是我遇到麻烦的地方。这是我的文件结构:

card
  | Card.svelte
  | Body.svelte
  | Header.svelte
  | Footer.svelte
  | index.ts

我的index.ts文件有以下代码:

import OriginalCard from './Card.svelte';
import Header from './Header.svelte';
import Footer from './Footer.svelte';
import Body from './Body.svelte';

const Card = OriginalCard;
Card.Header = Header;
Card.Body = Body;
Card.Footer = Footer;

export default Card;

页眉、正文和页脚均返回以下错误:

Property 'Header' does not exist on type 'typeof default'. ts(2339)

像这样使用组件时:

<script lang="ts>
  import Card from '@components/card';
</script>

<Card>
  <Card.Header>I am a Header</Card.Header>
  <Card.Body>I am a Body</Card.Body>
  <Card.Footer>I am a Footer</Card.Footer>
</Card>

页眉、正文和页脚均返回以下错误:

Property 'Body' does not exist on type 'typeof Card__SvelteComponent_'. ts(2339)

如何修复这些错误?

编辑

在另一个项目中安装此软件包后,我注意到接受的答案无法解决的两个问题:

1)。

<Card />
返回以下 ts 错误 - 预期 0 个参数,但得到 1。并破坏了允许属性的所有智能感知。

2)。智能感知不适用于点表示法。当输入

<Card.
时,我没有得到任何子组件的建议,而只是显示整个包中的所有组件。

期望的结果是没有 ts 错误并且不会丢失包的智能感知。

我还尝试像这样扩展

CardStatic
interface CardStatic extends OriginalCard
并且同样的问题继续存在。

typescript svelte svelte-component
2个回答
3
投票

您必须扩展已知类型才能添加其他属性。由于它们是静态的,我会尝试这样的事情:

const Card = OriginalCard as CardStatic;
Card.Header = Header;
Card.Body = Body;
Card.Footer = Footer;

export default Card;

export interface CardStatic {
    new(...args: ConstructorParameters<typeof OriginalCard>): OriginalCard;
    Header: typeof Header;
    Body: typeof Body;
    Footer: typeof Footer;
}

0
投票

当用于创建组件库时,我在 SvelteKit 中找到了一种更简单的方法:从 lib 文件夹的

index.ts
文件中导出名为 Card 的对象,如下所示:

import _Card from "./Card.svelte";
import _CardBody from "./CardBody.svelte";
import _CardHeader from "./CardHeader.svelte";
import _CardFooter from "./CardFooter.svelte";

export const Card = {
    Root: _Card,
    Footer: _CardFooter,
    Header: _CardHeader,
    Body: _CardBody
};

有了这个,您不需要额外的输入,但有一个问题:

<Card>
组件现在是
<Card.Root>
。它将从其他项目导入和使用,如下所示:

<script lang="ts">
    import { Card } from 'the-component-library';
</script>

<Card.Root>
    <Card.Header>My Header</Card.Header>
    <Card.Footer>My Footer</Card.Footer>
</Card.Root>

由于这个问题,我想说这不能被视为答案,但我仍然自愿,以防这个问题对人们来说是一件小事,而不是通过接受的答案提供的打字部分。

© www.soinside.com 2019 - 2024. All rights reserved.