-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
[feat] add convenience types ComponentType and ComponentProps #6770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
359b3ec
5fb01cc
3bd3107
2933bff
995c509
a8e616b
5902668
6940665
59638bb
df48d97
7ea67cf
2709f52
6082937
34cb5d2
13cc53c
e38f5b0
472c5a1
1f4190c
a4143c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -128,7 +128,7 @@ export interface SvelteComponentDev { | |
$destroy(): void; | ||
[accessor: string]: any; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file exports an interface There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also not part of this PR but wouldn't it be better to combine |
||
interface IComponentOptions<Props extends Record<string, any> = Record<string, any>> { | ||
export interface ComponentConstructorParams<Props extends Record<string, any> = Record<string, any>> { | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
target: Element | ShadowRoot; | ||
anchor?: Element; | ||
props?: Props; | ||
|
@@ -164,7 +164,7 @@ export class SvelteComponentDev extends SvelteComponent { | |
*/ | ||
$$slot_def: any; | ||
|
||
constructor(options: IComponentOptions) { | ||
constructor(options: ComponentConstructorParams) { | ||
if (!options || (!options.target && !options.$$inline)) { | ||
throw new Error("'target' is a required option"); | ||
} | ||
|
@@ -256,11 +256,47 @@ export class SvelteComponentTyped< | |
*/ | ||
$$slot_def: Slots; | ||
|
||
constructor(options: IComponentOptions<Props>) { | ||
constructor(options: ComponentConstructorParams<Props>) { | ||
super(options); | ||
} | ||
} | ||
|
||
/** | ||
* Convenience type to get the type of a Svelte component. Useful for example in combination with | ||
* dynamic components and `<svelte:element>`. | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* Example: | ||
* ```html | ||
* <script lang="ts"> | ||
* import type { ComponentType, SvelteComponentTyped } from 'svelte'; | ||
* import Component1 from './Component1.svelte'; | ||
* import Component2 from './Component2.svelte'; | ||
* | ||
* const component: ComponentType = someLogic() ? Component1 : Component2; | ||
* const componentOfCertainSubType: ComponentType<SvelteComponentTyped<{ needsThisProp: string }>> = someLogic() ? Component1 : Component2; | ||
* </script> | ||
* | ||
* <svelte:element this={component} /> | ||
* <svelte:element this={componentOfCertainSubType} needsThisProp="hello" /> | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* ``` | ||
*/ | ||
export type ComponentType<T extends SvelteComponentTyped = SvelteComponentTyped<any, any, any>> = | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
new (p: ComponentConstructorParams<T extends SvelteComponentTyped<infer X, any, any> ? X : any>) => T; | ||
ignatiusmb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
* Convenience type to get the props the given component expects. Example: | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* ```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<T extends SvelteComponent> = T extends SvelteComponentTyped<infer Props> | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
? Props | ||
: unknown; | ||
dummdidumm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export function loop_guard(timeout) { | ||
const start = Date.now(); | ||
return () => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// This script generates the TypeScript definitions | ||
|
||
const { execSync } = require('child_process'); | ||
const { readFileSync, writeFileSync } = require('fs'); | ||
|
||
execSync('tsc -p src/compiler --emitDeclarationOnly && tsc -p src/runtime --emitDeclarationOnly'); | ||
|
||
// We need to add these types to the index.d.ts here because if we add them before building, the build will fail, | ||
// because the TS->JS transformation doesn't know these exports are types and produces code that fails at runtime. | ||
// We can't use `export type` syntax either because the TS version we're on doesn't have this feature yet. | ||
const path = 'types/runtime/index.d.ts'; | ||
const content = readFileSync(path, 'utf8'); | ||
writeFileSync(path, content.replace('SvelteComponentTyped', 'SvelteComponentTyped, ComponentType, ComponentConstructorParams, ComponentProps')); |
Uh oh!
There was an error while loading. Please reload this page.