Skip to content

A way to pass Snippets with arguments as values outside of @render #14858

Closed as not planned
@hanielu

Description

@hanielu

Describe the problem

I need to pass snippets that take arguments across component boundaries, and for that, the Snippet type provided by svelte currently is not enough, there needs to be a utility function.

Describe the proposed solution

REPL Showcase

Currently I have this function that works, but Ideally something like this should be exported by svelte:

// Extract all parameters of a Snippet
type SnippetParams<T> = T extends Snippet<infer P> ? P : never;

// Helper type to create tuple of functions returning each type from a tuple
type TupleToFunctionTuple<T extends any[]> = {
  [K in keyof T]: () => T[K];
};

// Helper type to make it single function or tuple of functions based on length
type ParamFnsType<T extends any[]> = T extends [any]
  ? () => T[0] // Single parameter case
  : TupleToFunctionTuple<T>; // Multiple parameters case

/**
 * Converts a multi-parameter snippet into a single parameter snippet by providing fixed values for additional parameters
 *
 * @example
 *
 * // Original snippet with multiple parameters
 * {#snippet MainSnip(param1: string, param2: string)}
 *   <div>{param1} {param2}</div>
 * {/snippet}
 *
 * // Convert to single param snippet with fixed second param
 * const SnippetWithParam = bindSnippetArgs(MainSnip, () => "Bruzz")
 * // or with multiple fixed params
 * const SnippetWithParam2 = bindSnippetArgs(MainSnip, [() => "Bruzz", () => "Hello"])
 *
 * // Can now use with just one parameter
 * banner({title: "Hello"}, SnippetWithParam)
 * banner({title: "Hello"}, SnippetWithParam2)
 *
 * @param snippet - The original multi-parameter snippet to convert
 * @param paramFns - Function or array of functions that return fixed values for additional parameters
 * @returns A snippet that can be called with a `@render` tag
 */
export function bindSnippetArgs<T extends Snippet<any[]>>(snippet: T, paramFns: ParamFnsType<SnippetParams<T>>) {
  const fnsArray = Array.isArray(paramFns) ? paramFns : [paramFns];
  // @ts-expect-error Snippet typing is cooked
  return ((anchor: any) => snippet(anchor, ...fnsArray)) as Snippet;
}

Importance

would make my life easier

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions