Skip to content

Instantly share code, notes, and snippets.

@igor9silva
Created December 30, 2025 12:37
Show Gist options
  • Select an option

  • Save igor9silva/75514ad56e5bad708836c565f344a409 to your computer and use it in GitHub Desktop.

Select an option

Save igor9silva/75514ad56e5bad708836c565f344a409 to your computer and use it in GitHub Desktop.
Type-safe utility for accessing streaming promises from SvelteKit server load functions.
import { page } from '$app/state';
/**
* Type-safe utility for accessing streaming promises from SvelteKit server load functions.
*
* Solves two key problems:
* 1. **Prop drilling**: Components can access page.data.streaming directly without passing promises through parent components
* 2. **Type safety**: Infers exact promise types instead of unions, avoiding type guards everywhere
*
* @example
* in +page.server.ts:
* export const load = async ({ locals: { supabase } }) => {
*
* const chats = supabase.from('chats').select('*');
* const creatorMood: Record<string, Promise<TMoodData | null>> = {};
*
* creatorMood['creator-123'] = supabase.rpc('get_creator_mood', { id: 'creator-123' });
*
* return {
* streaming: { chats, creatorMood }
* };
* };
*
* in component (no prop drilling!):
* import { getStreamingPromise } from '$lib/utils/streaming';
* import type { PageData } from './$types';
*
* const moodPromise = getStreamingPromise<PageData>()('creatorMood', 'creator-123');
* ^? Promise<TMoodData | null>
*
* {#await moodPromise}
* Loading...
* {:then data}
* {data.mood_name}
* {/await}
*/
/**
* Creates a type-safe accessor for streaming promises from server load function page data.
*
* This lets TypeScript narrow the return type to the exact promise type (for the given streaming key)
* instead of a union of all possible streaming keys, avoiding the need for type guards.
*
* @template TPageData - The PageData type from +page.server.ts (imported via ./$types)
* @returns A function that accepts a streaming key and optional ID (for records)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intended
export function getStreamingPromise<TPageData extends { streaming?: Record<string, any> }>() {
//
// the returned function uses 'const TKey' to preserve the literal type of the key
// without 'const', TypeScript would widen 'creatorMood' to string, losing type information
return function <const TKey extends keyof NonNullable<TPageData['streaming']>>(
streamingKey: TKey,
id?: string,
): StreamingReturnType<TPageData, TKey> {
return getStreamingPromiseImpl<TPageData, TKey>(streamingKey, id);
};
}
/**
* Extracts the resolved value type from a streaming promise.
*
* Handles two patterns:
* 1. Direct promises: `streaming.chats -> Promise<TCustomerChat[]>`
* 2. Nested records: `streaming.creatorMood -> Record<creatorId, Promise<TMoodData>>`
*
* The conditional type checks if the value at TKey is a Record of promises (pattern 2)
* or a direct Promise (pattern 1), then infers the inner type V.
*
* @template TPageData - The page data type containing the streaming object
* @template TKey - The literal key type from the streaming object
*/
type StreamingReturnType<
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intended
TPageData extends { streaming?: Record<string, any> },
TKey extends keyof NonNullable<TPageData['streaming']>,
> = Promise<
TKey extends string
? NonNullable<TPageData['streaming']>[TKey] extends Record<string, Promise<infer V>>
? V
: NonNullable<TPageData['streaming']>[TKey] extends Promise<infer V>
? V
: never
: never
>;
/**
* Internal implementation that accesses page.data and extracts the promise.
*
* Accesses SvelteKit's page store directly, allowing components at any nesting level
* to fetch their data without receiving it as props from parents.
*
* Always returns a promise (even rejected ones) so components can use {#await} blocks without null checks.
*
* @template TPageData - The page data type
* @template TKey - The literal streaming key type
* @param streamingKey - The key in the streaming object
* @param id - Optional ID for nested record patterns (e.g., creatorId)
* @returns Promise of the data type, or rejected promise if not available
*/
function getStreamingPromiseImpl<
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intended
TPageData extends { streaming?: Record<string, any> },
const TKey extends keyof NonNullable<TPageData['streaming']>,
>(streamingKey: TKey, id?: string): StreamingReturnType<TPageData, TKey> {
//
// access the current page's data from SvelteKit's page store
// we cast to TPageData to get type safety on the streaming object
const pageData = page.data as unknown as TPageData;
const streaming = pageData.streaming?.[streamingKey as string];
// if the streaming key doesn't exist, return a rejected promise
// this ensures components always receive a promise (never null/undefined)
// so they can use {#await} blocks without null checks
if (!streaming) {
return Promise.reject(
new Error(`${String(streamingKey)} data not available`),
) as StreamingReturnType<TPageData, TKey>;
}
// handle nested record pattern: streaming.creatorMood[creatorId]
// this is used when we have multiple promises keyed by ID (e.g., one per creator)
if (id !== undefined) {
//
if (typeof streaming === 'object' && streaming !== null && id in streaming) {
//
const promise = (streaming as Record<string, Promise<unknown>>)[id];
if (promise) {
return promise as StreamingReturnType<TPageData, TKey>;
}
}
// if the ID doesn't exist in the record, return a rejected promise
return Promise.reject(
new Error(`${String(streamingKey)} data not available for ${id}`),
) as StreamingReturnType<TPageData, TKey>;
}
// when there's a single promise for the entire key, return it directly
return streaming as StreamingReturnType<TPageData, TKey>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment