Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte 5: Improve Snippet Typing to allow all types within a snippet body. #11537

Closed
arkmech opened this issue May 10, 2024 · 7 comments
Closed

Comments

@arkmech
Copy link

arkmech commented May 10, 2024

Describe the bug

    <Component children="Click me!" />

Component is a Svelte component that has a prop of children.

children is of type Snippet.

There should not be a TypeScript error for anything like strings, numbers, etc that are all allowable within a Snippet's body.

Error:
Type 'string' is not assignable to type '(this: void) => unique symbol & { _: "functions passed to {@render ...} tags must use the Snippet type imported from \"svelte\""; }'

Reproduction

Note: Reproduction is kinda pointless (as you don't actually see the TS error in REPL, only in VSCode.)

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE5VSy2rDMBD8lWUpJAGT3F3b9HEuBHqsenDtdSNqy0JahxSjfy-ylCdpIDdpmZmdGWnERrZkMf0YUZUdYYrPWmOC_Kv9xW6pZcIEbT-Yyk8yWxmpGdpSfecC2QoshBIsO90bhnVpSDE0pu9gtlyF6zLIzITKVoHuKSqL4Goj29qQygW-trL6gTcSWGSRXAiFCXZ9LRtJNaZsBnLJwe7LwNyrOx1D1SumHefCCw8txRC0m0JIxWSasiII6mvTawujRwjeu03hXUmtif3YXUa73ZL3CuNeAFzsK9b06BUEt8Qw7re59MxLDg_aH-aLy8VfE2paNj4ZUjWZQ8HzxeTzCLnZbKj__r8AEFMGwwmMIe-pf3f4IWG6PI9-fIBgIpBox6Rqe_4o7kpVp6T_m6rldqopC3rFUSCLrgpPibArVX26Pz4IXXs_AwAA

Logs

No response

System Info

System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 771.97 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.1.0 - /opt/homebrew/bin/node
    Yarn: 1.22.22 - /opt/homebrew/bin/yarn
    npm: 10.7.0 - /opt/homebrew/bin/npm
    pnpm: 9.1.0 - /opt/homebrew/bin/pnpm
    bun: 1.1.7 - /opt/homebrew/bin/bun
  Browsers:
    Chrome: 124.0.6367.156
    Safari: 17.4.1

Severity

annoyance

@dummdidumm
Copy link
Member

Your code snippet wouldn't work if I pass the string "Click me" to the Button component directly, so the error is correct. It works in your REPL because the prop you're passing into Parent turns from a string into a snippet by being rendered in the Button component. In this case you should adjust the typings yourself in the Parent component.

@dummdidumm dummdidumm closed this as not planned Won't fix, can't repro, duplicate, stale May 10, 2024
@arkmech
Copy link
Author

arkmech commented May 10, 2024

So is it not possible to pass snippet body content through a prop? Is there a type of contents within a Snippet body? I want to extend the Button’s children prop (Snippet body) to parent because the prop is going into the Snippet body.

how would you type the Parent for anything that goes into Snippet body?

string | number | ComponentType<SvelteComponent> | Snippet

@brunnerh
Copy link
Member

If you do {children} in the template, that can have any value at all, i.e. the type could just be any. But that would not automatically render snippets if you pass any.

I don't really understand the point of this, though. By not using snippets you just limit the capabilities.

@arkmech
Copy link
Author

arkmech commented May 11, 2024

If you do {children} in the template, that can have any value at all, i.e. the type could just be any. But that would not automatically render snippets if you pass any.

I don't really understand the point of this, though. By not using snippets you just limit the capabilities.

Take a scenario like this:

content and trigger are both snippets. I want to maintain this ergonomic component API

<script lang="ts">
  import Accordion, { type AccordionItems } from "$lib/components/shared/Accordion/Accordion.svelte";

  const accordionItems: AccordionItems = [
    {
      value: 'one',
      trigger: "One",
      content: 'This is content three'
    },
    {
      value: 'one',
      trigger: "Two",
      content: 'This is content two'
    },
  ]
</script>

<Accordion items={accordionItems} />

accordion-svelte

I wanted to avoid typing any as much as possible

@brunnerh
Copy link
Member

brunnerh commented May 11, 2024

If you want to accept strings and snippets, just accept strings and snippets.
Any other primitive can easily be converted to a string.

To render that, you need to differentiate, otherwise real snippets will not work.

{#if typeof content == 'string'}
	{content}
{:else}
	{@render content()}
{/if}

@arkmech
Copy link
Author

arkmech commented May 11, 2024

Technically I can never accept a snippet due to component API. Can’t pass snippet through props. It’s a loop

I will just try to imitate this https://reactnative.dev/docs/react-node

as a type that can go in SnippetBody.

@brunnerh
Copy link
Member

Sure you can pass snippets through props.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants