Skip to content

5.33.2, SvelteHTMLElements and generics issues #16046

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

Closed
rChaoz opened this issue May 31, 2025 · 2 comments
Closed

5.33.2, SvelteHTMLElements and generics issues #16046

rChaoz opened this issue May 31, 2025 · 2 comments

Comments

@rChaoz
Copy link
Contributor

rChaoz commented May 31, 2025

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

@paoloricciuti
Copy link
Member

So I'm not seeing the same errors that you see...for example this component works perfectly fine for me except for the union too complex error.

Image

I suspect you have two version of svelte somehow and that's conflicting.

However the Union too complex error is definitely a problem and a bit annoying...dunno if we can do something about it so we might need to revert that change.

@JLAcostaEC
Copy link

JLAcostaEC commented Jun 5, 2025

Well, the same thing happened to me. I was looking for a solution, saw this issue, and after updating, the error still persisted. For me, the only way to fix it was to use a utility I have within the project that omits types by X word to omit all Svelte < v5 on: types, and everything was fixed.

Util:

export type OmitByWord<T, K extends string> = {
  [P in keyof T as P extends `${string}${K}${string}` ? never : P]: T[P];
};

And then in the component type:

export type SomeComponentProps<T extends 'ul' | 'ol' | 'div' = 'ul'> = {
  // Props Here...
} & OmitByWord<SvelteHTMLElements[T], 'on:'>;

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

No branches or pull requests

5 participants