Skip to content

5.33.2, SvelteHTMLElements and generics issues #16046

@rChaoz

Description

@rChaoz

Describe the bug

After upgrading from 5.33.1 to 5.33.2, a bunch of errors started appearing in my CI (sv check). I believe the errors are caused by #15972, and they mostly affect <svelte:element> and generic components.

For example:

<script lang="ts" generics="Tag extends keyof SvelteHTMLElements">
    import type { SvelteHTMLElements } from "svelte/elements"
    const { tag }: { tag: Tag } = $props()
</script>

<svelte:element this={tag} class="test" />

This used to work, but now has a type error:

Error: Argument of type '{ class: string; }' is not assignable to parameter of type 'string extends Tag ? HTMLAttributes<any> : IntrinsicElements[Tag]'. (ts)

Or another example:

<script lang="ts" generics="Tag extends keyof SvelteHTMLElements">
    import type { SvelteHTMLElements } from "svelte/elements"

    const test: Tag extends string ? any : any = { class: "string" }
</script>

fails with

Error: Type '{ class: string; }' is not assignable to type 'Tag extends string ? any : any'. (ts)

which is odd, to say the least. No matter whether the condition is true or false, the type should be any, thus bypassing all type checks, yet there is an error - it seems the condition Tag extends string is neither true nor false (Schrodinger style), and TypeScript gets confused. It's worth noting that keyof SvelteHTMLElements does, in fact, extend string, so I'm unsure why TypeScript thinks that Tag, which extends keyof SvelteHTMLElements, doesn't. I think someone with better TypeScript knowledge can help here, as I have no clue what's going on.

Finally, I think the main issue here is that, because of this, polymorphic components are broken, for example:

<script lang="ts" generics="Tag extends keyof SvelteHTMLElements">
    import type { SvelteHTMLElements } from "svelte/elements"

    type Props = SvelteHTMLElements[Tag] & {
        as: Tag
    }

    const { as, ...rest }: Props = $props()
</script>

<svelte:element this={as} {...rest} />

now has two errors:

Error: Argument of type 'Omit<Props, "as">' is not assignable to parameter of type 'string extends Tag | (undefined & Tag) | (null & Tag) | ("" & Tag) | ("object" & Tag) | ("json" & Tag) | ("style" & Tag) | ("image" & Tag) | ... 18 more ... | ("webidentity" & Tag) ? HTMLAttributes<...> : IntrinsicElements[Tag | ... 25 more ... | ("webidentity" & Tag)]'.

Error: Expression produces a union type that is too complex to represent.

I consider myself decent with TypeScript, but after a couple of hours of trying things out I concluded that it's pretty much impossible to code anything that works with keyof SvelteHTMLElements. The workaround is to use Tag extends string, it seems to work correctly as before.

Severity

annoyance

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions