Skip to content

Commit

Permalink
custom contructor approach
Browse files Browse the repository at this point in the history
  • Loading branch information
dummdidumm committed Apr 17, 2024
1 parent 73bfe71 commit 811b1ce
Show file tree
Hide file tree
Showing 26 changed files with 104 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -327,43 +327,6 @@ function adjustIfNecessary(diagnostic: Diagnostic): Diagnostic {
};
}

if (diagnostic.code === DiagnosticCode.UNKNOWN_PROP) {
// Remove confusing type helper stuff from diagnostic message
let start = diagnostic.message.indexOf('__sveltets_2_Bindings<');
if (start !== -1) {
const startType = start + '__sveltets_2_Bindings<'.length;
const end = traverseTypeString(diagnostic.message, startType, ',');
diagnostic.message =
diagnostic.message.substring(0, start) +
diagnostic.message.substring(startType, end) +
"'.";
} else {
start = diagnostic.message.indexOf('WithBindings<__sveltets_2_Bindings<');
if (start !== -1) {
const startType = start + 'WithBindings<__sveltets_2_Bindings<'.length;
const end = traverseTypeString(diagnostic.message, startType, ',');
diagnostic.message =
diagnostic.message.substring(0, start) +
diagnostic.message.substring(startType, end) +
"'.";
} else {
start = diagnostic.message.indexOf('PropsWithChildren<');
if (start !== -1) {
const startType = start + 'PropsWithChildren<'.length;
const end = traverseTypeString(diagnostic.message, startType, ',');
const type = diagnostic.message.substring(startType, end);
diagnostic.message = diagnostic.message.substring(0, start) + type + "'.";
diagnostic.message = diagnostic.message.replaceAll(' & "_explicit_"', '');
}
}
}

return {
...diagnostic,
message: diagnostic.message
};
}

if (
(diagnostic.code === DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y ||
diagnostic.code === DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y_DID_YOU_MEAN) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
},
"severity": 1,
"source": "ts",
"message": "Object literal may only specify known properties, and '\"invalidProp\"' does not exist in type 'WithBindings<$$Props>'.",
"message": "Object literal may only specify known properties, and '\"invalidProp\"' does not exist in type 'WithBindings<{ exported1: string; exported2?: string | undefined; exported3: string; }>'.",
"code": 2353,
"tags": []
},
{
"range": { "start": { "line": 12, "character": 1 }, "end": { "line": 12, "character": 6 } },
"severity": 1,
"source": "ts",
"message": "Type '{}' is missing the following properties from type 'WithBindings<$$Props>': exported1, exported3",
"message": "Type '{}' is missing the following properties from type 'WithBindings<{ exported1: string; exported2?: string | undefined; exported3: string; }>': exported1, exported3",
"code": 2739,
"tags": []
}
Expand Down
15 changes: 15 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx/addComponentExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ class __sveltets_Render${genericsDef} {
const [EventsName] = addTypeExport(str, className, 'Events');
const [SlotsName] = addTypeExport(str, className, 'Slots');

let customConstructor = '';
if (exportedNames.usesRunes()) {
customConstructor = `\n constructor(options: import('svelte').ComponentConstructorOptions<__sveltets_2_PropsWithChildren<${returnType('props')}, ${returnType('slots')}>>) { super(options); }`;
}

if (mode === 'dts') {
statement +=
`export type ${PropsName}${genericsDef} = ${returnType('props')};\n` +
Expand All @@ -88,6 +93,7 @@ class __sveltets_Render${genericsDef} {
`\n${doc}export default class${
className ? ` ${className}` : ''
}${genericsDef} extends ${svelteComponentClass}<${PropsName}${genericsRef}, ${EventsName}${genericsRef}, ${SlotsName}${genericsRef}> {` +
customConstructor +
exportedNames.createClassGetters() +
(usesAccessors ? exportedNames.createClassAccessors() : '') +
'\n}';
Expand All @@ -99,6 +105,7 @@ class __sveltets_Render${genericsDef} {
}${genericsDef} extends __SvelteComponentTyped__<${returnType('props')}, ${returnType(
'events'
)}, ${returnType('slots')}> {` +
customConstructor +
exportedNames.createClassGetters() +
(usesAccessors ? exportedNames.createClassAccessors() : '') +
'\n}';
Expand Down Expand Up @@ -129,6 +136,11 @@ function addSimpleComponentExport({
const doc = componentDocumentation.getFormatted();
const className = fileName && classNameFromFilename(fileName, mode !== 'dts');

let customConstructor = '';
if (exportedNames.usesRunes()) {
customConstructor = `\n constructor(options = __sveltets_2_runes_constructor(${propDef})) { super(options); }`;
}

let statement: string;
if (mode === 'dts' && isTsFile) {
const svelteComponentClass = noSvelteComponentTyped
Expand All @@ -146,6 +158,7 @@ function addSimpleComponentExport({
`\n${doc}export default class${
className ? ` ${className}` : ''
} extends ${svelteComponentClass}<${PropsName}, ${EventsName}, ${SlotsName}> {` +
customConstructor +
exportedNames.createClassGetters() +
(usesAccessors ? exportedNames.createClassAccessors() : '') +
'\n}';
Expand All @@ -158,6 +171,7 @@ function addSimpleComponentExport({
`\n${doc}export default class${
className ? ` ${className}` : ''
} extends __sveltets_2_createSvelte2TsxComponent(${propDef}) {` +
customConstructor +
exportedNames.createClassGetters() +
(usesAccessors ? exportedNames.createClassAccessors() : '') +
'\n}';
Expand All @@ -166,6 +180,7 @@ function addSimpleComponentExport({
`\n\n${doc}export default class${
className ? ` ${className}` : ''
} extends __sveltets_2_createSvelte2TsxComponent(${propDef}) {` +
customConstructor +
exportedNames.createClassGetters() +
(usesAccessors ? exportedNames.createClassAccessors() : '') +
'\n}';
Expand Down
1 change: 1 addition & 0 deletions packages/svelte2tsx/src/svelte2tsx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ export function svelte2tsx(
const str = new MagicString(svelte);
const basename = path.basename(options.filename || '');
const svelte5Plus = Number(options.version![0]) > 4;

// process the htmlx as a svelte template
let {
htmlAst,
Expand Down
4 changes: 4 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -722,4 +722,8 @@ export class ExportedNames {
getExportsMap() {
return this.exports;
}

usesRunes() {
return this.$props.type || this.$props.comment;
}
}
16 changes: 14 additions & 2 deletions packages/svelte2tsx/svelte-shims-v4.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ declare function __sveltets_2_with_any<Props = {}, Events = {}, Slots = {}>(

declare function __sveltets_2_with_any_event<Props = {}, Events = {}, Slots = {}>(
render: {props: Props, events: Events, slots: Slots }
): {props: Props, events: Events & {[evt: string]: CustomEvent<any>;}, slots: Slots }
): {props: Expand<Props>, events: Events & {[evt: string]: CustomEvent<any>;}, slots: Slots }

declare function __sveltets_2_store_get<T = any>(store: SvelteStore<T>): T
declare function __sveltets_2_store_get<Store extends SvelteStore<any> | undefined | null>(store: Store): Store extends SvelteStore<infer T> ? T : Store;
Expand Down Expand Up @@ -234,7 +234,19 @@ declare type __sveltets_2_Bindings<Props extends Record<string, any>, Bindings e
// @ts-ignore not available in Svelte 4
import('svelte').Bindable<Props[K]> :
Props[K]
} & '_explicit_';
};
declare function __sveltets_2_binding<T>(prop: T):
// @ts-ignore not available in Svelte 4
import('svelte').Binding<T>;

type __sveltets_2_PropsWithChildren<Props, Slots> = Props &
(Slots extends { default: any }
// This is unfortunate because it means "accepts no props" turns into "accepts any prop"
// but the alternative is non-fixable type errors because of the way TypeScript index
// signatures work (they will always take precedence and make an impossible-to-satisfy children type).
? Props extends Record<string, never>
? any
// @ts-ignore not available in Svelte 4
: { children?: import('svelte').Snippet<[any]> }
: {});
declare function __sveltets_2_runes_constructor<Props extends {}, Events extends {}, Slots extends {}>(render: {props: Props, events: Events, slots: Slots }): import("svelte").ComponentConstructorOptions<__sveltets_2_PropsWithChildren<Props, Slots>>;
12 changes: 11 additions & 1 deletion packages/svelte2tsx/test/emitDts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as assert from 'assert';
import * as fs from 'fs';
import { join } from 'path';
import { emitDts } from '../../src';
import { VERSION } from 'svelte/compiler';

function rimraf(path: string) {
((fs as any).rmSync || fs.rmdirSync)(path, { recursive: true, force: true });
Expand All @@ -10,13 +11,22 @@ function rimraf(path: string) {
async function testEmitDts(sample: string) {
const cwd = join(__dirname, 'samples', sample);

if (sample.endsWith('.v5') && +VERSION[0] < 5) {
return; // skip
}

try {
const config = fs.existsSync(join(cwd, 'config.json'))
? JSON.parse(fs.readFileSync(join(cwd, 'config.json'), 'utf-8'))
: {};
await emitDts({
declarationDir: 'package',
svelteShimsPath: require.resolve(join(process.cwd(), 'svelte-shims.d.ts')), // TODO make it -v4 once we have Svelte 4 in the workspace
svelteShimsPath: require.resolve(
join(
process.cwd(),
sample.endsWith('.v5') ? 'svelte-shims-v4.d.ts' : 'svelte-shims.d.ts'
)
), // TODO make it -v4 once we have Svelte 4 in the workspace
...config,
libRoot: config.libRoot ? join(cwd, config.libRoot) : join(cwd, 'src')
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SvelteComponent } from "svelte";
declare const __propDef: {
props: {
foo: string;
bar?: import("svelte").Bindable<number>;
baz?: () => void;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {};
};
export type TestRunesProps = typeof __propDef.props;
export type TestRunesEvents = typeof __propDef.events;
export type TestRunesSlots = typeof __propDef.slots;
export default class TestRunes extends SvelteComponent<TestRunesProps, TestRunesEvents, TestRunesSlots> {
constructor(options?: import("svelte").ComponentConstructorOptions<{
foo: string;
bar?: import("svelte").Bindable<number>;
baz?: () => void;
}>);
get baz(): () => void;
}
export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script lang="ts">
let { foo, bar = $bindable() }: { foo: string, bar?: number } = $props();
export function baz() {}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "es2020",
"lib": ["es2020", "DOM"],
"target": "es2019",
"isolatedModules": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"allowJs": true,
"checkJs": true
},
"include": ["./src/**/*.d.ts", "./src/**/*.js", "./src/**/*.ts", "./src/**/*.svelte"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ async () => {};
return { props: /** @type {$$ComponentProps} */({}), slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ async () => {};
return { props: /** @type {__sveltets_2_Bindings<$$ComponentProps, "b">} */({}), slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ state; derived;};
return { props: /** @type {$$ComponentProps} */({}), slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ async () => {
return { props: /** @type {SomeType} */({}), slots: {'default': {x:x, y:y}}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ async () => {};
return { props: /** @type {$$ComponentProps} */({}), slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ async () => {};
return { props: /** @type {{snapshot?: typeof snapshot} & $$ComponentProps} */({}), slots: {}, events: {} }}

export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render())))) { super(options); }
get snapshot() { return __sveltets_2_nonNullable(this.$$prop_def.snapshot) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ async () => {};
return { props: /** @type {{snapshot?: typeof snapshot} & $$ComponentProps} */({}), slots: {}, events: {} }}

export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render())))) { super(options); }
get snapshot() { return __sveltets_2_nonNullable(this.$$prop_def.snapshot) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ async () => {};
return { props: {} as any as $$ComponentProps, slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_with_any_event(render())) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_with_any_event(render()))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ async () => {};
return { props: {} as any as __sveltets_2_Bindings<$$ComponentProps, "b">, slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_with_any_event(render())) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_with_any_event(render()))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ class __sveltets_Render<T> {

import { SvelteComponentTyped as __SvelteComponentTyped__ } from "svelte"
export default class Input__SvelteComponent_<T> extends __SvelteComponentTyped__<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> {
constructor(options: import('svelte').ComponentConstructorOptions<__sveltets_2_PropsWithChildren<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['slots']>>>) { super(options); }
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ class __sveltets_Render<T> {

import { SvelteComponentTyped as __SvelteComponentTyped__ } from "svelte"
export default class Input__SvelteComponent_<T> extends __SvelteComponentTyped__<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> {
constructor(options: import('svelte').ComponentConstructorOptions<__sveltets_2_PropsWithChildren<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['slots']>>>) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ async () => {};
return { props: {} as any as $$ComponentProps, slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_with_any_event(render())) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_with_any_event(render()))) { super(options); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ async () => {};
return { props: {} as any as $$ComponentProps & { snapshot?: any }, slots: {}, events: {} }}

export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_with_any_event(render())) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_with_any_event(render()))) { super(options); }
get snapshot() { return __sveltets_2_nonNullable(this.$$prop_def.snapshot) }
}
Loading

0 comments on commit 811b1ce

Please sign in to comment.