Skip to content

Instantly share code, notes, and snippets.

@pushkine
Last active February 9, 2021 09:37
Show Gist options
  • Save pushkine/d2ebc3e7131f7a658e5ca7bdf0150574 to your computer and use it in GitHub Desktop.
Save pushkine/d2ebc3e7131f7a658e5ca7bdf0150574 to your computer and use it in GitHub Desktop.
Accurate typings for Svelte's compiler output, includes comments for ambiguous properties and type functions for advanced use cases
interface LifecycleFunction {
(): void;
}
interface EventCallback<T = unknown> {
(event: CustomEvent<T>): void;
}
export namespace Svelte {
export interface Fragment {
key?: string | null;
first?: Comment | null;
c(): void;
l?(nodes: any): void;
h?(): void;
m(target: HTMLElement, anchor: HTMLElement): void;
p(ctx: ctx, dirty: dirtyUpdate): void;
r?(): void;
f?(): void;
a?(): void;
i?(local: 0 | 1 | boolean): void;
o?(local: 0 | 1 | boolean): void;
d(detaching: 0 | 1 | boolean): void;
}
export interface CreateFragment {
(ctx: ctx): Svelte.Fragment;
}
export type ctx = any[];
export type dirty = number[];
export type dirtyUpdate = number | dirty;
export type scopeInit = { readonly ctx: ctx };
export type scopeUpdate = { readonly ctx: ctx; readonly dirty: dirtyUpdate };
export namespace Slot {
export interface Init {
$$slots: {
default?: Template;
[name: string]: Template;
};
$$scope: {
ctx: ctx;
};
}
export interface Update {
$$scope?: {
ctx: ctx;
dirty: dirtyUpdate;
};
}
export interface UpdateLetCtx {
(ctx_lets: { [let_name: string]: unknown }): { [lets_index_in_ctx: number]: unknown };
}
export interface DirtyLet {
(dirty_lets: { [let_name: string]: boolean }): dirtyUpdate;
}
export type Template = [CreateFragment] | [CreateFragment, UpdateLetCtx, DirtyLet];
}
type Props = { [prop_name: string]: any };
type Events = { [event_name: string]: any };
type Slots = { [slot_name: string]: { [let_name: string]: any } } | {};
export namespace Component {
export interface Instance<P extends Props = {}, E extends Events = {}, S extends Slots = {}> {
readonly __proto__?: { readonly constructor: Constructor<P, E, S> };
$$prop_def: P; // svelte extension only
$$events_def: E; // svelte extension only
$$slot_def: S; // svelte extension only
$$: T$$;
$$set?: ($$props: Partial<P> & Slot.Update) => void;
$set(props: Partial<P> & Slot.Update): void;
$on<K extends keyof E & string>(event: K, handler: (e: CustomEvent<E[K]>) => void): () => void;
$destroy(): void;
$capture_state?(): void;
$inject_state?(): void;
}
export interface T$$ {
fragment: Svelte.Fragment; // fragment | false (no markup) | null (destroyed)
update: () => void; // updates reactive statements
dirty: dirty;
ctx: ctx;
bound: Record<number, (value: unknown) => void>; // prop index in ctx -> bind callback
skip_bound: boolean; // prevents upstream bindings callbacks when props flow downstream
callbacks: { [event_name: string]: EventCallback[] }; // event listener callbacks
props: { [prop_name: string]: number }; // index in ctx
not_equal: (a: any, b: any) => boolean;
context: Map<any, any>;
on_mount: LifecycleFunction[];
on_destroy: LifecycleFunction[];
before_update: LifecycleFunction[];
after_update: LifecycleFunction[];
}
export interface StandaloneOptions<P extends Props = {}> {
props?: P;
target: HTMLElement;
anchor?: HTMLElement;
hydrate?: boolean;
intro?: boolean;
}
export interface CompiledOptions<P extends Props = {}> {
props?: Slot.Init & Omit<P, keyof Slot.Init>;
$$inline?: boolean; // avoids "no target" dev-mode warning when using CompiledOptions
}
export type Options<P extends Props = {}> = StandaloneOptions<P> | CompiledOptions<P> | {};
export interface Constructor<P extends Props = {}, E extends Events = {}, S extends Slots = {}> {
new (options: Options<P>): Instance<P, E, S>;
}
}
type ExtractDef<T, K extends string> = (T extends new (...args: any[]) => infer U ? U : T) extends {
[_ in `$$${K}_def`]: infer U;
}
? U
: never;
type Spread<T, U> = { [K in keyof T | keyof U]: K & keyof U extends never ? T[K & keyof T] : U[K & keyof U] };
export type PropsOf<T> = ExtractDef<T, "prop">;
export type EventsOf<T> = ExtractDef<T, "events">;
export type SlotsOf<T> = ExtractDef<T, "slot">;
export type OptionsOf<T> = Component.Options<PropsOf<T>>;
export type ConstructorOf<T> = Component.Constructor<PropsOf<T>, EventsOf<T>, SlotsOf<T>>;
export type InstanceOf<T> = Component.Instance<PropsOf<T>, EventsOf<T>, SlotsOf<T>>;
export type PropKeyOf<T> = keyof PropsOf<T> & string;
export type PropValueOf<T, K extends PropKeyOf<T> = PropKeyOf<T>> = PropsOf<T>[K];
export type SpreadProps<A, B> = Spread<PropsOf<A>, PropsOf<B>>;
export type SpreadEvents<A, B> = Spread<EventsOf<A>, EventsOf<B>>;
export type SpreadSlots<A, B> = Spread<SlotsOf<A>, SlotsOf<B>>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment