Skip to content

Enable attachment to enhance typings on applied element #16678

@vnphanquang

Description

@vnphanquang

Describe the problem

Before Svelte attachment, Svelte action allows specifying additional attributes (including custom event listeners) on the element it is placed on:

export interface ActionReturn<
Parameter = undefined,
Attributes extends Record<string, any> = Record<never, any>
> {
update?: (parameter: Parameter) => void;
destroy?: () => void;
/**
* ### DO NOT USE THIS
* This exists solely for type-checking and has no effect at runtime.
* Set this through the `Attributes` generic instead.
*/
$$_attributes?: Attributes;

For example:

<script lang="ts">
  import { type ActionReturn } from 'svelte/action';

	interface ClickOutsideAttributes {
		musthave: string;
		onclickoutside?: (event: CustomEvent) => void;
	}

  function clickoutside(node: Element): ActionReturn<void, ClickOutsideAttributes> {
		/* ... */
		return {};
	}
</script>

<dialog use:clickoutside musthave="something">
	<!-- ... -->
</dialog>

As one would expect, the editor tooling will pick up onclickoutside as optional, and musthave as required - a nice ergonomics for element enhancement. I am missing this handy feature when using attachment, especially as a lib author.

Having this level of feature parity is also nice to encourage attachment over action, which I think is the right direction going forward. The action docs seems to suggest so too:

This module provides types for actions, which have been superseded by attachments.

Describe the proposed solution

The current Attachment interface...

export interface Attachment<T extends EventTarget = Element> {
(element: T): void | (() => void);
}

...can perhaps become:

	export interface Attachment<
		Element extends EventTarget = Element,
		Attributes extends Record<string, any> = Record<never, any>,
	> {
		(element: Element): void | AttachmentReturn<Attributes>
	}

	export interface AttachmentReturn<
		Attributes extends Record<string, any> = Record<never, any>
	> {
		(): void;
		/**
		 * ### DO NOT USE THIS
		 * This exists solely for type-checking and has no effect at runtime.
		 * Set this through the `Attributes` generic instead.
		 */
		$$_attributes?: Attributes;
	}

fromAction can infer accordingly.

I suspect, however, much of the work required for this is on the language-tools side. Svelte attachment can also live within an object being spread onto the element, and I am not sure if that indicates any additional complexity.

Related artifacts:

Originally discussed in #16676

Importance

nice to have

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