Skip to content

Using clsx incorporating class declaration with tailwind-merge causes error #14874

Open
@mpost

Description

@mpost

Describe the bug

Combining the latest clsx supporting HTMLAttributes with tailwind-merge creates type incompatibility.

HTMLAttributes declared by svelte

export interface HTMLAttributes<T extends EventTarget> extends AriaAttributes, DOMAttributes<T> {
	class?: string | import('clsx').ClassArray | import('clsx').ClassDictionary | undefined | null;
	...
}

Expected type from tailwind-merge

export type ClassNameValue = ClassNameArray | string | 0 | 0n | false | undefined | null

Error Logs

Argument of type 'string | ClassArray | ClassDictionary | null | undefined' is not assignable to parameter of type 'ClassNameValue'.
  Type 'ClassArray' is not assignable to type 'ClassNameValue'.
    Type 'ClassValue[]' is not assignable to type 'ClassNameArray'.
      Type 'ClassValue' is not assignable to type 'ClassNameValue'.
        Type 'number' is not assignable to type 'ClassNameValue'. (ts)
          : 'size-12',
    cssClass,
  )}

Reproduction

<script lang="ts">
  import { twMerge } from 'tailwind-merge'
  import type { HTMLButtonAttributes } from 'svelte/elements'
  import type { Snippet } from 'svelte'

  interface Props extends HTMLButtonAttributes {
    children?: Snippet
  }

  let { class: cssClass, children, ...rest }: Props = $props()
</script>

<button {...rest} class={twMerge('rounded', cssClass)}>
  {@render children?.()}
</button>

System Info

npmPackages:
    svelte: ^5.16.0
    tailwind-merge: ^2.6.0

Severity

blocking an upgrade

Hacky workaround

One possibility is to redefine the class property as a common type (eg a simple string).

  interface Props extends HTMLButtonAttributes {
    children?: Snippet
    class?: string
  }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions