Skip to content

Commit

Permalink
Revert typed SvelteComponent, add SvelteComponentTyped instead (#5738)
Browse files Browse the repository at this point in the history
  • Loading branch information
dummdidumm authored Dec 2, 2020
1 parent 307b86b commit 79214cc
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ It's the last "What's new in Svelte" of the year and there's lots to celebrate!

1. `$$props`, `$$restProps`, and `$$slots` are all now supported in custom web components (**3.29.5**, [Example](https://svelte.dev/repl/ad8e6f39cd20403dacd1be84d71e498d?version=3.29.5)) and `slot` components now support spread props: `<slot {...foo} />` (**3.30.0**)
2. A new `hasContext` lifecycle function makes it easy to check whether a `key` has been set in the context of a parent component (**3.30.0** & **3.30.1**, [Docs](https://svelte.dev/docs#hasContext))
3. `SvelteComponent` is now typed which makes it easier to add typed classes that extend base Svelte Components. Component library and framework authors rejoice! An example: `export class YourComponent extends SvelteComponent<{aProp: boolean}, {click: MouseEvent}, {default: {aSlot: string}}> {}` (**3.30.0**, [RFC](https://github.com/sveltejs/rfcs/pull/37))
3. There is now a new `SvelteComponentTyped` class which makes it easier to add strongly typed components that extend base Svelte components. Component library and framework authors rejoice! An example: `export class YourComponent extends SvelteComponentTyped<{aProp: boolean}, {click: MouseEvent}, {default: {aSlot: string}}> {}` (**3.30.0**, [RFC](https://github.com/sveltejs/rfcs/pull/37))
4. Transitions within `{:else}` blocks should now complete successfully (**3.29.5**, [Example](https://svelte.dev/repl/49cef205e5da459594ef2eafcbd41593?version=3.29.5))
5. Svelte now includes an export map, which explicitly states which files can be imported from its npm package (**3.29.5** with some fixes in **3.29.6**, **3.29.7** and **3.30.0**)
6. `rollup-plugin-svelte` had a new [7.0.0 release](https://github.com/sveltejs/rollup-plugin-svelte/blob/master/CHANGELOG.md). The biggest change is that the `css` option was removed. Users who were using that option should add another plugin like `rollup-plugin-css-only` as demonstrated [in the template](https://github.com/sveltejs/template/blob/5b1135c286f7a649daa99825a077586655051649/rollup.config.js#L48)
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export {
hasContext,
tick,
createEventDispatcher,
SvelteComponentDev as SvelteComponent
SvelteComponentDev as SvelteComponent,
SvelteComponentTyped
} from 'svelte/internal';
14 changes: 7 additions & 7 deletions src/runtime/internal/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,19 +212,19 @@ if (typeof HTMLElement === 'function') {
};
}

export class SvelteComponent<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any
> {
/**
* Base class for Svelte components. Used when dev=false.
*/
export class SvelteComponent {
$$: T$$;
$$set?: ($$props: Partial<Props>) => void;
$$set?: ($$props: any) => void;

$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}

$on<K extends Extract<keyof Events, string>>(type: K, callback: (e: Events[K]) => void) {
$on(type, callback) {
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
callbacks.push(callback);

Expand All @@ -234,7 +234,7 @@ export class SvelteComponent<
};
}

$set($$props: Partial<Props>) {
$set($$props) {
if (this.$$set && !is_empty($$props)) {
this.$$.skip_bound = true;
this.$$set($$props);
Expand Down
107 changes: 86 additions & 21 deletions src/runtime/internal/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,57 @@ export function validate_slots(name, slot, keys) {
}
}

export interface SvelteComponentDev<
type Props = Record<string, any>;
export interface SvelteComponentDev {
$set(props?: Props): void;
$on(event: string, callback: (event: any) => void): () => void;
$destroy(): void;
[accessor: string]: any;
}
/**
* Base class for Svelte components with some minor dev-enhancements. Used when dev=true.
*/
export class SvelteComponentDev extends SvelteComponent {
/**
* @private
* For type checking capabilities only.
* Does not exist at runtime.
* ### DO NOT USE!
*/
$$prop_def: Props;

constructor(options: {
target: Element;
anchor?: Element;
props?: Props;
hydrate?: boolean;
intro?: boolean;
$$inline?: boolean;
}) {
if (!options || (!options.target && !options.$$inline)) {
throw new Error("'target' is a required option");
}

super();
}

$destroy() {
super.$destroy();
this.$destroy = () => {
console.warn('Component was already destroyed'); // eslint-disable-line no-console
};
}

$capture_state() {}

$inject_state() {}
}

// TODO https://github.com/microsoft/TypeScript/issues/41770 is the reason
// why we have to split out SvelteComponentTyped to not break existing usage of SvelteComponent.
// Try to find a better way for Svelte 4.0.

export interface SvelteComponentTyped<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
Expand All @@ -107,12 +157,42 @@ export interface SvelteComponentDev<
$destroy(): void;
[accessor: string]: any;
}

export class SvelteComponentDev<
/**
* Base class to create strongly typed Svelte components.
* This only exists for typing purposes and should be used in `.d.ts` files.
*
* ### Example:
*
* You have component library on npm called `component-library`, from which
* you export a component called `MyComponent`. For Svelte+TypeScript users,
* you want to provide typings. Therefore you create a `index.d.ts`:
* ```ts
* import { SvelteComponentTyped } from "svelte";
* export class MyComponent extends SvelteComponentTyped<{foo: string}> {}
* ```
* Typing this makes it possible for IDEs like VS Code with the Svelte extension
* to provide intellisense and to use the component like this in a Svelte file
* with TypeScript:
* ```svelte
* <script lang="ts">
* import { MyComponent } from "component-library";
* </script>
* <MyComponent foo={'bar'} />
* ```
*
* #### Why not make this part of `SvelteComponent(Dev)`?
* Because
* ```ts
* class ASubclassOfSvelteComponent extends SvelteComponent<{foo: string}> {}
* const component: typeof SvelteComponent = ASubclassOfSvelteComponent;
* ```
* will throw a type error, so we need to seperate the more strictly typed class.
*/
export class SvelteComponentTyped<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
> extends SvelteComponent<Props, Events> {
> extends SvelteComponentDev {
/**
* @private
* For type checking capabilities only.
Expand Down Expand Up @@ -142,24 +222,9 @@ export class SvelteComponentDev<
hydrate?: boolean;
intro?: boolean;
$$inline?: boolean;
}) {
if (!options || (!options.target && !options.$$inline)) {
throw new Error("'target' is a required option");
}

super();
}) {
super(options);
}

$destroy() {
super.$destroy();
this.$destroy = () => {
console.warn('Component was already destroyed'); // eslint-disable-line no-console
};
}

$capture_state() {}

$inject_state() {}
}

export function loop_guard(timeout) {
Expand Down

0 comments on commit 79214cc

Please sign in to comment.