Skip to content

Commit

Permalink
fix: support function invocation from imported *.svelte components
Browse files Browse the repository at this point in the history
When the TypeScript plugin we provide isn't enabled, imports to `.svelte`-files fall back to an ambient module declaration. Said declaration was still only providing the deprecated class. This PR widens the type so that you can also invoke it like a function. After the transition period (Svelte 6 or 7) only the new type should be provided from the module declaration.
  • Loading branch information
dummdidumm committed Jun 17, 2024
1 parent a1b6cc6 commit 634e308
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-days-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

fix: support function invocation from imported `*.svelte` components
13 changes: 12 additions & 1 deletion packages/svelte/src/ambient.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
declare module '*.svelte' {
export { SvelteComponent as default } from 'svelte';
import { SvelteComponent, Component, type ComponentConstructorOptions } from 'svelte';

// Support using the component as both a class and function during the transition period
interface ComponentType {
(
...args: Parameters<Component<Record<string, any>>>
): ReturnType<Component<Record<string, any>, Record<string, any>>>;
new (o: ComponentConstructorOptions): SvelteComponent;
}
const Comp: ComponentType;
type Comp = SvelteComponent;
export default Comp;
}

/**
Expand Down
10 changes: 10 additions & 0 deletions packages/svelte/tests/types/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,13 @@ render(functionComponent, {
x: ''
}
});

// --------------------------------------------------------------------------- *.svelte components

// import from a nonexistent file to trigger the declare module '*.svelte' in ambient.d.ts
// this could show an error in the future in the editor (because language tools intercepts and knows this is an error)
// but should always pass in tsc (because it will never know about this fact)
import Foo from './doesntexist.svelte';

Foo(null, { a: true });
const f: Foo = new Foo({ target: document.body, props: { a: true } });
13 changes: 12 additions & 1 deletion packages/svelte/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2634,7 +2634,18 @@ declare module 'svelte/types/compiler/interfaces' {
*/
type Namespace = 'html' | 'svg' | 'mathml' | 'foreign';
}declare module '*.svelte' {
export { SvelteComponent as default } from 'svelte';
import { SvelteComponent, Component, type ComponentConstructorOptions } from 'svelte';

// Support using the component as both a class and function during the transition period
interface ComponentType {
(
...args: Parameters<Component<Record<string, any>>>
): ReturnType<Component<Record<string, any>, Record<string, any>>>;
new (o: ComponentConstructorOptions): SvelteComponent;
}
const Comp: ComponentType;
type Comp = SvelteComponent;
export default Comp;
}

/**
Expand Down

0 comments on commit 634e308

Please sign in to comment.