Skip to content

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

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
hanielu opened this issue Dec 29, 2024 · 2 comments
Closed

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

hanielu opened this issue Dec 29, 2024 · 2 comments

Comments

@hanielu
Copy link

hanielu commented Dec 29, 2024

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

@webJose
Copy link
Contributor

webJose commented Dec 29, 2024

I believe it is a duplicate of #10678.

@paoloricciuti
Copy link
Member

I believe it is a duplicate of #10678.

Correct...therefore closing

@paoloricciuti paoloricciuti closed this as not planned Won't fix, can't repro, duplicate, stale Dec 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants