working on types :loading:

pull/8569/head
S. Elliott Johnson 3 years ago
parent 0fadf733fc
commit 68adbc18ae

@ -95,7 +95,7 @@ export function init(
) { ) {
const parent_component = current_component; const parent_component = current_component;
set_current_component(component); set_current_component(component);
/** @type {T$$} */ /** @type {import('.').T$$} */
const $$ = (component.$$ = { const $$ = (component.$$ = {
fragment: null, fragment: null,
ctx: [], ctx: [],
@ -163,8 +163,11 @@ if (typeof HTMLElement === 'function') {
$$connected = false; $$connected = false;
$$data = {}; $$data = {};
$$reflecting = false; $$reflecting = false;
/** @type {Record<string, CustomElementPropDefinition>} */
$$props_definition = {}; $$props_definition = {};
/** @type {Record<string, Function[]>} */
$$listeners = {}; $$listeners = {};
/** @type {Map<Function, Function>} */
$$listener_unsubscribe_fns = new Map(); $$listener_unsubscribe_fns = new Map();
constructor($$componentCtor, $$slots, use_shadow_dom) { constructor($$componentCtor, $$slots, use_shadow_dom) {
@ -310,7 +313,7 @@ if (typeof HTMLElement === 'function') {
* @param {string} prop * @param {string} prop
* @param {any} value * @param {any} value
* @param {Record<string, CustomElementPropDefinition>} props_definition * @param {Record<string, CustomElementPropDefinition>} props_definition
* @param {'toAttribute' | 'toProp'} transform * @param {'toAttribute' | 'toProp'} [transform]
* @returns {any} * @returns {any}
*/ */
function get_custom_element_value(prop, value, props_definition, transform) { function get_custom_element_value(prop, value, props_definition, transform) {
@ -349,12 +352,11 @@ function get_custom_element_value(prop, value, props_definition, transform) {
* @internal * @internal
* *
* Turn a Svelte component into a custom element. * Turn a Svelte component into a custom element.
* @param {ComponentType} Component A Svelte component constructor * @param {import('./dev').ComponentType} Component A Svelte component constructor
* @param {Record<string, CustomElementPropDefinition>} props_definition The props to observe * @param {Record<string, CustomElementPropDefinition>} props_definition The props to observe
* @param {string[]} slots The slots to create * @param {string[]} slots The slots to create
* @param {string[]} accessors Other accessors besides the ones for props the component has * @param {string[]} accessors Other accessors besides the ones for props the component has
* @param {boolean} use_shadow_dom Whether to use shadow DOM * @param {boolean} use_shadow_dom Whether to use shadow DOM
* @returns {Class<Class>} A custom element class
*/ */
export function create_custom_element( export function create_custom_element(
Component, Component,
@ -410,7 +412,7 @@ export function create_custom_element(
} }
}); });
}); });
Component.element = Class; Component.element = /** @type {any} */ (Class);
return Class; return Class;
} }

@ -65,10 +65,10 @@ ResizeObserverSingleton.entries = 'WeakMap' in globals ? new WeakMap() : undefin
/** /**
* @typedef {Object} ResizeObserverEntry * @typedef {Object} ResizeObserverEntry
* @property {readonlyResizeObserverSize[]} borderBoxSize * @property {readonly ResizeObserverSize[]} borderBoxSize
* @property {readonlyResizeObserverSize[]} contentBoxSize * @property {readonly ResizeObserverSize[]} contentBoxSize
* @property {DOMRectReadOnly} contentRect * @property {DOMRectReadOnly} contentRect
* @property {readonlyResizeObserverSize[]} devicePixelContentBoxSize * @property {readonly ResizeObserverSize[]} devicePixelContentBoxSize
* @property {Element} target * @property {Element} target
*/ */

@ -106,5 +106,5 @@ export function add_transform(node, a) {
* node: Element, * node: Element,
* { from, to }: { from: PositionRect; to: PositionRect }, * { from, to }: { from: PositionRect; to: PositionRect },
* params: any * params: any
* ) => AnimationConfig} AnimationFn * ) => import('../animate').AnimationConfig} AnimationFn
*/ */

@ -4,6 +4,7 @@ import { flush } from './scheduler.js';
import { get_current_component, set_current_component } from './lifecycle.js'; import { get_current_component, set_current_component } from './lifecycle.js';
/** /**
* @template T
* @param {Promise<T>} promise * @param {Promise<T>} promise
* @param {PromiseInfo<T>} info * @param {PromiseInfo<T>} info
* @returns {boolean} * @returns {boolean}
@ -11,9 +12,10 @@ import { get_current_component, set_current_component } from './lifecycle.js';
export function handle_promise(promise, info) { export function handle_promise(promise, info) {
const token = (info.token = {}); const token = (info.token = {});
/** /**
* @param {FragmentFactory} type * @param {import('.').FragmentFactory} type
* @param {0 | 1 | 2} index * @param {0 | 1 | 2} index
* @param {number} key * @param {number} [key]
* @param {any} [value]
* @returns {void} * @returns {void}
*/ */
function update(type, index, key, value) { function update(type, index, key, value) {
@ -99,6 +101,7 @@ export function update_await_block_branch(info, ctx, dirty) {
/** /**
* @typedef {Object} PromiseInfo * @typedef {Object} PromiseInfo
* @template T
* @property {null|any} ctx * @property {null|any} ctx
* @property {{}} token * @property {{}} token
* @property {boolean} hasCatch * @property {boolean} hasCatch

@ -0,0 +1,94 @@
import type { SvelteComponent } from './Component';
export interface SvelteComponentDev<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any // eslint-disable-line @typescript-eslint/no-unused-vars
> {
$set(props?: Partial<Props>): void;
$on<K extends Extract<keyof Events, string>>(
type: K,
callback: ((e: Events[K]) => void) | null | undefined
): () => void;
$destroy(): void;
[accessor: string]: any;
}
export interface ComponentConstructorOptions<
Props extends Record<string, any> = Record<string, any>
> {
target: Element | Document | ShadowRoot;
anchor?: Element;
props?: Props;
context?: Map<any, any>;
hydrate?: boolean;
intro?: boolean;
$$inline?: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface SvelteComponentTyped<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
> extends SvelteComponentDev<Props, Events, Slots> {}
/**
* Convenience type to get the type of a Svelte component. Useful for example in combination with
* dynamic components using `<svelte:component>`.
*
* Example:
* ```html
* <script lang="ts">
* import type { ComponentType, SvelteComponent } from 'svelte';
* import Component1 from './Component1.svelte';
* import Component2 from './Component2.svelte';
*
* const component: ComponentType = someLogic() ? Component1 : Component2;
* const componentOfCertainSubType: ComponentType<SvelteComponent<{ needsThisProp: string }>> = someLogic() ? Component1 : Component2;
* </script>
*
* <svelte:component this={component} />
* <svelte:component this={componentOfCertainSubType} needsThisProp="hello" />
* ```
*/
export type ComponentType<Component extends SvelteComponentDev = SvelteComponentDev> = (new (
options: ComponentConstructorOptions<
Component extends SvelteComponentDev<infer Props> ? Props : Record<string, any>
>
) => Component) & {
/** The custom element version of the component. Only present if compiled with the `customElement` compiler option */
element?: typeof HTMLElement;
};
/**
* Convenience type to get the props the given component expects. Example:
* ```html
* <script lang="ts">
* import type { ComponentProps } from 'svelte';
* import Component from './Component.svelte';
*
* const props: ComponentProps<Component> = { foo: 'bar' }; // Errors if these aren't the correct props
* </script>
* ```
*/
export type ComponentProps<Component extends SvelteComponent> =
Component extends SvelteComponentDev<infer Props> ? Props : never;
/**
* Convenience type to get the events the given component expects. Example:
* ```html
* <script lang="ts">
* import type { ComponentEvents } from 'svelte';
* import Component from './Component.svelte';
*
* function handleCloseEvent(event: ComponentEvents<Component>['close']) {
* console.log(event.detail);
* }
* </script>
*
* <Component on:close={handleCloseEvent} />
* ```
*/
export type ComponentEvents<Component extends SvelteComponent> =
Component extends SvelteComponentDev<any, infer Events> ? Events : never;

@ -13,6 +13,7 @@ import { is_void } from '../../shared/utils/names.js';
import { contenteditable_truthy_values } from './utils.js'; import { contenteditable_truthy_values } from './utils.js';
/** /**
* @template T
* @param {string} type * @param {string} type
* @param {T} detail * @param {T} detail
* @returns {void} * @returns {void}
@ -179,7 +180,7 @@ export function set_data_dev(text, data) {
data = '' + data; data = '' + data;
if (text.data === data) return; if (text.data === data) return;
dispatch_dev('SvelteDOMSetData', { node: text, data }); dispatch_dev('SvelteDOMSetData', { node: text, data });
text.data = data; text.data = /** @type {string} */ (data);
} }
/** /**
@ -191,7 +192,7 @@ export function set_data_contenteditable_dev(text, data) {
data = '' + data; data = '' + data;
if (text.wholeText === data) return; if (text.wholeText === data) return;
dispatch_dev('SvelteDOMSetData', { node: text, data }); dispatch_dev('SvelteDOMSetData', { node: text, data });
text.data = data; text.data = /** @type {string} */ (data);
} }
/** /**
@ -293,6 +294,9 @@ export function construct_svelte_component_dev(component, props) {
* </script> * </script>
* <MyComponent foo={'bar'} /> * <MyComponent foo={'bar'} />
* ``` * ```
* @template {Record<string, any>} Props
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
* @extends SvelteComponent * @extends SvelteComponent
*/ */
export class SvelteComponentDev extends SvelteComponent { export class SvelteComponentDev extends SvelteComponent {
@ -302,6 +306,7 @@ export class SvelteComponentDev extends SvelteComponent {
* Does not exist at runtime. * Does not exist at runtime.
* ### DO NOT USE! * ### DO NOT USE!
*/ */
/** @type {Props} */
$$prop_def = undefined; $$prop_def = undefined;
/** /**
* @private * @private
@ -309,6 +314,7 @@ export class SvelteComponentDev extends SvelteComponent {
* Does not exist at runtime. * Does not exist at runtime.
* ### DO NOT USE! * ### DO NOT USE!
*/ */
/** @type {Events} */
$$events_def = undefined; $$events_def = undefined;
/** /**
* @private * @private
@ -316,13 +322,16 @@ export class SvelteComponentDev extends SvelteComponent {
* Does not exist at runtime. * Does not exist at runtime.
* ### DO NOT USE! * ### DO NOT USE!
*/ */
/** @type {Slots} */
$$slot_def = undefined; $$slot_def = undefined;
constructor(options) { constructor(options) {
if (!options || (!options.target && !options.$$inline)) { if (!options || (!options.target && !options.$$inline)) {
throw new Error("'target' is a required option"); throw new Error("'target' is a required option");
} }
super(); super();
} }
/** @returns {void} */ /** @returns {void} */
$destroy() { $destroy() {
super.$destroy(); super.$destroy();
@ -330,16 +339,22 @@ export class SvelteComponentDev extends SvelteComponent {
console.warn('Component was already destroyed'); // eslint-disable-line no-console console.warn('Component was already destroyed'); // eslint-disable-line no-console
}; };
} }
/** @returns {void} */ /** @returns {void} */
$capture_state() {} $capture_state() {}
/** @returns {void} */ /** @returns {void} */
$inject_state() {} $inject_state() {}
} }
/** /**
* @template {Record<string, any>} Props
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
* @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512 * @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512
* @extends SvelteComponentDev<Props, Events, Slots> * @extends SvelteComponentDev<Props, Events, Slots>
*/ */
export class SvelteComponentTyped extends SvelteComponentDev {} export class SvelteComponentTyped extends SvelteComponentDev {}
/** @returns {() => void} */ /** @returns {() => void} */
export function loop_guard(timeout) { export function loop_guard(timeout) {
const start = Date.now(); const start = Date.now();
@ -349,29 +364,3 @@ export function loop_guard(timeout) {
} }
}; };
} }
/**
* @typedef {Class<HTMLElement>} ComponentType
* @template {SvelteComponentDev} [Component=SvelteComponentDev]
*/
/**
* @typedef {Component extends SvelteComponentDev<infer Props> ? Props : never} ComponentProps
* @template {SvelteComponent} Component
*/
/**
* @typedef {Component extends SvelteComponentDev<any, infer Events> ? Events : never} ComponentEvents
* @template {SvelteComponent} Component
*/
/** @typedef {Object} SvelteComponentDev */
/**
* @typedef {Object} ComponentConstructorOptions
* @property {Element|Document|ShadowRoot} target
* @property {Element} [anchor]
* @property {Props} [props]
* @property {Map<any,any>} [context]
* @property {boolean} [hydrate]
* @property {boolean} [intro]
* @property {boolean} [$$inline]
*/
/** @typedef {Object} SvelteComponentTyped */

@ -0,0 +1,18 @@
export interface EventDispatcher<EventMap extends Record<string, any>> {
// Implementation notes:
// - undefined extends X instead of X extends undefined makes this work better with both strict and nonstrict mode
// - [X] extends [never] is needed, X extends never would reduce the whole resulting type to never and not to one of the condition outcomes
<Type extends keyof EventMap>(
...args: [EventMap[Type]] extends [never]
? [type: Type, parameter?: null | undefined, options?: DispatchOptions]
: null extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type], options?: DispatchOptions]
: undefined extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type], options?: DispatchOptions]
: [type: Type, parameter: EventMap[Type], options?: DispatchOptions]
): boolean;
}
export interface DispatchOptions {
cancelable?: boolean;
}

@ -36,6 +36,7 @@ export function beforeUpdate(fn) {
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api). * `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
* *
* https://svelte.dev/docs#run-time-svelte-onmount * https://svelte.dev/docs#run-time-svelte-onmount
* @template T
* @param {() => T extends Promise<() => any> * @param {() => T extends Promise<() => any>
* ? "Returning a function asynchronously from onMount won't call that function on destroy" * ? "Returning a function asynchronously from onMount won't call that function on destroy"
* : T} fn * : T} fn
@ -90,7 +91,8 @@ export function onDestroy(fn) {
* ``` * ```
* *
* https://svelte.dev/docs#run-time-svelte-createeventdispatcher * https://svelte.dev/docs#run-time-svelte-createeventdispatcher
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/lifecycle.ts-to-jsdoc").EventDispatcher<EventMap>} * @template {Record<string, any>} EventMap
* @returns {import('./lifecycle').EventDispatcher<EventMap>}
*/ */
export function createEventDispatcher() { export function createEventDispatcher() {
const component = get_current_component(); const component = get_current_component();
@ -99,7 +101,7 @@ export function createEventDispatcher() {
if (callbacks) { if (callbacks) {
// TODO are there situations where events could be dispatched // TODO are there situations where events could be dispatched
// in a server (non-DOM) environment? // in a server (non-DOM) environment?
const event = custom_event(type, detail, { cancelable }); const event = custom_event(/** @type {string} */ (type), detail, { cancelable });
callbacks.slice().forEach((fn) => { callbacks.slice().forEach((fn) => {
fn.call(component, event); fn.call(component, event);
}); });
@ -117,6 +119,7 @@ export function createEventDispatcher() {
* Like lifecycle functions, this must be called during component initialisation. * Like lifecycle functions, this must be called during component initialisation.
* *
* https://svelte.dev/docs#run-time-svelte-setcontext * https://svelte.dev/docs#run-time-svelte-setcontext
* @template T
* @param {T} context * @param {T} context
* @returns {T} * @returns {T}
*/ */
@ -130,6 +133,7 @@ export function setContext(key, context) {
* Must be called during component initialisation. * Must be called during component initialisation.
* *
* https://svelte.dev/docs#run-time-svelte-getcontext * https://svelte.dev/docs#run-time-svelte-getcontext
* @template T
* @returns {T} * @returns {T}
*/ */
export function getContext(key) { export function getContext(key) {
@ -142,6 +146,7 @@ export function getContext(key) {
* programmatically create a component and want to pass the existing context to it. * programmatically create a component and want to pass the existing context to it.
* *
* https://svelte.dev/docs#run-time-svelte-getallcontexts * https://svelte.dev/docs#run-time-svelte-getallcontexts
* @template T
* @returns {T} * @returns {T}
*/ */
export function getAllContexts() { export function getAllContexts() {

@ -28,7 +28,7 @@ export function clear_loops() {
* Creates a new task that runs on each raf frame * Creates a new task that runs on each raf frame
* until it returns a falsy value or is aborted * until it returns a falsy value or is aborted
* @param {TaskCallback} callback * @param {TaskCallback} callback
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/loop.ts-to-jsdoc").Task} * @returns {Task}
*/ */
export function loop(callback) { export function loop(callback) {
/** @type {TaskEntry} */ /** @type {TaskEntry} */
@ -49,5 +49,6 @@ export function loop(callback) {
/** /**
* @typedef {Object} Task * @typedef {Object} Task
* @property {() => void} abort
* @property {Promise<void>} promise * @property {Promise<void>} promise
*/ */

@ -66,7 +66,7 @@ export function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
/** /**
* @param {Element & ElementCSSInlineStyle} node * @param {Element & ElementCSSInlineStyle} node
* @param {string} name * @param {string} [name]
* @returns {void} * @returns {void}
*/ */
export function delete_rule(node, name) { export function delete_rule(node, name) {

@ -4,14 +4,17 @@ export function noop() {}
/** @returns {any} */ /** @returns {any} */
export const identity = (x) => x; export const identity = (x) => x;
/** @param {T} tar /**
* @template T
* @template S
* @param {T} tar
* @param {S} src * @param {S} src
* @returns {T & S} * @returns {T & S}
*/ */
export function assign(tar, src) { export function assign(tar, src) {
// @ts-ignore // @ts-ignore
for (const k in src) tar[k] = src[k]; for (const k in src) tar[k] = src[k];
return tar; return /** @type {T & S} */ (tar);
} }
// Adapted from https://github.com/then/is-promise/blob/master/index.js // Adapted from https://github.com/then/is-promise/blob/master/index.js
@ -103,7 +106,9 @@ export function subscribe(store, ...callbacks) {
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
} }
/** @param {Readable<T>} store /**
* @template T
* @param {import('../store').Readable<T>} store
* @returns {T} * @returns {T}
*/ */
export function get_store_value(store) { export function get_store_value(store) {

@ -13,7 +13,7 @@ const subscriber_queue = [];
* Creates a `Readable` store that allows reading by subscription. * Creates a `Readable` store that allows reading by subscription.
* @param {T} value initial value * @param {T} value initial value
* @param {StartStopNotifier<T>} start undefined * @param {StartStopNotifier<T>} start undefined
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").Readable<T>} * @returns {Readable<T>}
*/ */
export function readable(value, start) { export function readable(value, start) {
return { return {

@ -10,6 +10,8 @@
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"svelte/*": ["*"] "svelte/*": ["*"]
} },
"allowJs": true,
"checkJs": true
} }
} }

Loading…
Cancel
Save