I am working on a component library that has a bit of a twist on how components are grouped. I am grouping components into classes to make using the library simpler for end users. Rather than remembering which named slots
are available they would instead access the custom slots using a dot notation. For example, a Card
component could have a Header
, Body
, and a Footer
. In my library I would like to use these componets like so:
<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>
I have this working currently but I am trying to get this strongly typed as well and that is where I am running into trouble. Here is my file structure:
card
| Card.svelte
| Body.svelte
| Header.svelte
| Footer.svelte
| index.ts
My index.ts file has the following code:
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;
Header, Body, & Footer all return the following error: Property 'Header' does not exist on type 'typeof default'. ts(2339)
When using the component like so:
<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>
Header, Body, & Footer all return the following error: Property 'Body' does not exist on type 'typeof Card__SvelteComponent_'. ts(2339)
How do I fix these errors?
EDIT
After installing this package in another project I noticed two issues that the accepted answer does not solve:
1). <Card />
returns the following ts error - Expected 0 arguments, but got 1. and breaks all intellisense for the allowable properties.
2). Intellisense does not work with the dot notation. When typing <Card.
I am not getting suggestions for any of the sub-components and instead it is just showing all components in the entire package.
The desired outcome is to not have the ts errors and not lose intellisense with the package.
I also attempted to extend the CardStatic
like so:
interface CardStatic extends OriginalCard
and the same issues continued to persist.
You have to extend the known type to add the additional properties. Since they are static I would try something like this:
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;
}