feat: add `ComponentExports` utility type (#13441)

Safer/clearer/backwards/forward-compatibale way to reference them

---------

Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
pull/14064/head
FoHoOV 2 months ago committed by GitHub
parent 3999fed4ca
commit d93ad3ba1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
chore: provide `ComponentExports` utility type

@ -237,6 +237,26 @@ export type ComponentProps<Comp extends SvelteComponent | Component<any, any>> =
? Props ? Props
: never; : never;
/**
* Convenience type to get the properties that given component exports.
*
* Example: Typing the `bind:this` for a component named `MyComponent`
* ```
* <script lang="ts">
* import MyComponent from '$lib/component';
* let component: ComponentExports<typeof MyComponent> | undefined = undefined;
* <script>
*
* <MyComponent bind:this={component} />
* ```
*/
export type ComponentExports<TComponent extends Component<any, any> | typeof SvelteComponent<any>> =
TComponent extends typeof SvelteComponent<any>
? InstanceType<TComponent>
: TComponent extends Component<any, infer TExports>
? TExports
: never;
/** /**
* @deprecated This type is obsolete when working with the new `Component` type. * @deprecated This type is obsolete when working with the new `Component` type.
* *

@ -7,7 +7,8 @@ import {
mount, mount,
hydrate, hydrate,
type Component, type Component,
type ComponentInternals type ComponentInternals,
type ComponentExports
} from 'svelte'; } from 'svelte';
import { render } from 'svelte/server'; import { render } from 'svelte/server';
@ -180,6 +181,16 @@ render(NewComponent, {
} }
}); });
const newComponentExports: ComponentExports<typeof NewComponent> = {
anExport: '',
$$events_def: null as any,
$$prop_def: null as any,
$$slot_def: null as any,
$set: null as any,
$destroy: null as any,
$on: null as any
};
// --------------------------------------------------------------------------- interop // --------------------------------------------------------------------------- interop
const AsLegacyComponent = asClassComponent(newComponent); const AsLegacyComponent = asClassComponent(newComponent);
@ -337,6 +348,19 @@ render(functionComponent, {
} }
}); });
const functionComponentExports: ComponentExports<typeof functionComponent> = {
foo: 'bar',
// @ts-expect-error
x: ''
};
type AdhocFunctionComponent = (a: unknown, b: { a: true }) => { foo: string };
const adhocFunctionComponentExport: ComponentExports<AdhocFunctionComponent> = {
foo: 'bar',
// @ts-expect-error
x: ''
};
// --------------------------------------------------------------------------- *.svelte components // --------------------------------------------------------------------------- *.svelte components
// import from a nonexistent file to trigger the declare module '*.svelte' in ambient.d.ts // import from a nonexistent file to trigger the declare module '*.svelte' in ambient.d.ts

@ -234,6 +234,26 @@ declare module 'svelte' {
? Props ? Props
: never; : never;
/**
* Convenience type to get the properties that given component exports.
*
* Example: Typing the `bind:this` for a component named `MyComponent`
* ```
* <script lang="ts">
* import MyComponent from '$lib/component';
* let component: ComponentExports<typeof MyComponent> | undefined = undefined;
* <script>
*
* <MyComponent bind:this={component} />
* ```
*/
export type ComponentExports<TComponent extends Component<any, any> | typeof SvelteComponent<any>> =
TComponent extends typeof SvelteComponent<any>
? InstanceType<TComponent>
: TComponent extends Component<any, infer TExports>
? TExports
: never;
/** /**
* @deprecated This type is obsolete when working with the new `Component` type. * @deprecated This type is obsolete when working with the new `Component` type.
* *

Loading…
Cancel
Save