From f89079b3c25066d453369a957b5489d53bab53b3 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 31 Aug 2021 11:54:42 +0200 Subject: [PATCH 1/4] (fix) transform interface to type in dts mode #1126 --- packages/svelte2tsx/src/svelte2tsx/index.ts | 8 +++- .../processInstanceScriptContent.ts | 41 ++++++++++++++++++- .../typescript/expected/Test2.svelte.d.ts | 4 ++ .../samples/typescript/src/Interfaces.svelte | 12 ++++++ .../samples/typescript/src/Test2.svelte | 4 ++ .../transforms-interfaces-dts/expected.tsx | 31 ++++++++++++++ .../transforms-interfaces-dts/input.svelte | 14 +++++++ 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 packages/svelte2tsx/test/emitDts/samples/typescript/src/Interfaces.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte diff --git a/packages/svelte2tsx/src/svelte2tsx/index.ts b/packages/svelte2tsx/src/svelte2tsx/index.ts index 19b53cba8..da6a31d69 100644 --- a/packages/svelte2tsx/src/svelte2tsx/index.ts +++ b/packages/svelte2tsx/src/svelte2tsx/index.ts @@ -336,7 +336,13 @@ export function svelte2tsx( if (scriptTag.start != instanceScriptTarget) { str.move(scriptTag.start, scriptTag.end, instanceScriptTarget); } - const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues); + const res = processInstanceScriptContent( + str, + scriptTag, + events, + implicitStoreValues, + options.mode + ); uses$$props = uses$$props || res.uses$$props; uses$$restProps = uses$$restProps || res.uses$$restProps; uses$$slots = uses$$slots || res.uses$$slots; diff --git a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts index fc698843b..5c057cbed 100644 --- a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts +++ b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts @@ -36,7 +36,8 @@ export function processInstanceScriptContent( str: MagicString, script: Node, events: ComponentEvents, - implicitStoreValues: ImplicitStoreValues + implicitStoreValues: ImplicitStoreValues, + mode: 'tsx' | 'dts' ): InstanceScriptProcessResult { const htmlx = str.original; const scriptContent = htmlx.substring(script.content.start, script.content.end); @@ -375,6 +376,14 @@ export function processInstanceScriptContent( str.appendRight(firstImport.getStart() + astOffset, '\n'); } + if (mode === 'dts') { + // Transform interface declarations to type declarations because indirectly + // using interfaces inside the return type of a function is forbidden. + // This is not a problem for intellisense/type inference but it will + // break dts generation (file will not be generated). + transformInterfacesToTypes(tsAst, str, astOffset); + } + return { exportedNames, events, @@ -385,3 +394,33 @@ export function processInstanceScriptContent( generics }; } + +function transformInterfacesToTypes(tsAst: ts.SourceFile, str: MagicString, astOffset: any) { + tsAst.statements.filter(ts.isInterfaceDeclaration).forEach((node) => { + str.overwrite( + node.getStart() + astOffset, + node.getStart() + astOffset + 'interface'.length, + 'type' + ); + + if (node.heritageClauses?.length) { + const extendsStart = str.original.indexOf('extends', node.getStart() + astOffset); + str.overwrite(extendsStart, extendsStart + 'extends'.length, '='); + + const extendsList = node.heritageClauses[0].types; + let prev = extendsList[0]; + extendsList.slice(1).forEach((heritageClause) => { + str.overwrite( + prev.getEnd() + astOffset, + heritageClause.getStart() + astOffset, + ' & ' + ); + prev = heritageClause; + }); + + str.appendLeft(node.heritageClauses[0].getEnd() + astOffset, ' & '); + } else { + str.prependLeft(str.original.indexOf('{', node.getStart() + astOffset), '='); + } + }); +} diff --git a/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts b/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts index 45e91c48b..07833357e 100644 --- a/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts +++ b/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts @@ -1,8 +1,12 @@ import { SvelteComponentTyped } from "svelte"; import type { Foo } from './foo'; +interface Bar { + a: true; +} declare const __propDef: { props: { foo: Foo; + bar: Bar; }; events: { [evt: string]: CustomEvent; diff --git a/packages/svelte2tsx/test/emitDts/samples/typescript/src/Interfaces.svelte b/packages/svelte2tsx/test/emitDts/samples/typescript/src/Interfaces.svelte new file mode 100644 index 000000000..2112d179f --- /dev/null +++ b/packages/svelte2tsx/test/emitDts/samples/typescript/src/Interfaces.svelte @@ -0,0 +1,12 @@ + diff --git a/packages/svelte2tsx/test/emitDts/samples/typescript/src/Test2.svelte b/packages/svelte2tsx/test/emitDts/samples/typescript/src/Test2.svelte index aef3fb6f6..91da875cb 100644 --- a/packages/svelte2tsx/test/emitDts/samples/typescript/src/Test2.svelte +++ b/packages/svelte2tsx/test/emitDts/samples/typescript/src/Test2.svelte @@ -1,4 +1,8 @@ diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx new file mode 100644 index 000000000..e5807f4a2 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx @@ -0,0 +1,31 @@ +import { SvelteComponentTyped } from "svelte" + +declare function __sveltets_1_createSvelteComponentTyped( + render: {props: Props, events: Events, slots: Slots } +): SvelteComponentConstructor,Svelte2TsxComponentConstructorParameters>; + + +import type { Foo } from './foo'; +function render() { + + + let foo: Foo; + type Bar1 ={ + a: true; + } + type Bar2 = Bar1 & { + b: false; + } + type Bar3 = Bar1 & Bar2 & { + c: false; + } + let bar: Bar3; +; +return { props: {foo: foo , bar: bar}, slots: {}, getters: {}, events: {} }} +const __propDef = __sveltets_1_partial(__sveltets_1_with_any_event(render())); +/** @typedef {typeof __propDef.props} InputProps */ +/** @typedef {typeof __propDef.events} InputEvents */ +/** @typedef {typeof __propDef.slots} InputSlots */ + +export default class Input extends __sveltets_1_createSvelteComponentTyped(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte new file mode 100644 index 000000000..23a066d79 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte @@ -0,0 +1,14 @@ + From 7a005f0fd8a424b556e48a04b5f7b899ff3f53ca Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 31 Aug 2021 11:56:54 +0200 Subject: [PATCH 2/4] missed --- .../expected/Interfaces.svelte.d.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 packages/svelte2tsx/test/emitDts/samples/typescript/expected/Interfaces.svelte.d.ts diff --git a/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Interfaces.svelte.d.ts b/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Interfaces.svelte.d.ts new file mode 100644 index 000000000..4fa904ecf --- /dev/null +++ b/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Interfaces.svelte.d.ts @@ -0,0 +1,20 @@ +import { SvelteComponentTyped } from "svelte"; +declare class __sveltets_Render { + props(): { + a: T; + }; + events(): { + b: CustomEvent; + }; + slots(): { + default: { + c: T; + }; + }; +} +export declare type InterfacesProps = ReturnType<__sveltets_Render['props']>; +export declare type InterfacesEvents = ReturnType<__sveltets_Render['events']>; +export declare type InterfacesSlots = ReturnType<__sveltets_Render['slots']>; +export default class Interfaces extends SvelteComponentTyped, InterfacesEvents, InterfacesSlots> { +} +export {}; From 60d1b0ed886270bb8d2e5ca296d7d38edf74a6ca Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 31 Aug 2021 12:02:04 +0200 Subject: [PATCH 3/4] fix test --- .../emitDts/samples/typescript/expected/Test2.svelte.d.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts b/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts index 07833357e..f7c09ebd1 100644 --- a/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts +++ b/packages/svelte2tsx/test/emitDts/samples/typescript/expected/Test2.svelte.d.ts @@ -1,12 +1,11 @@ import { SvelteComponentTyped } from "svelte"; import type { Foo } from './foo'; -interface Bar { - a: true; -} declare const __propDef: { props: { foo: Foo; - bar: Bar; + bar: { + a: true; + }; }; events: { [evt: string]: CustomEvent; From 93dc8b6dbc317c2c1169a944e5b667b1a3fd7738 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Wed, 1 Sep 2021 14:18:49 +0200 Subject: [PATCH 4/4] fix extends case --- .../svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts | 2 +- .../svelte2tsx/samples/transforms-interfaces-dts/expected.tsx | 3 +++ .../svelte2tsx/samples/transforms-interfaces-dts/input.svelte | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts index 5c057cbed..30ade9142 100644 --- a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts +++ b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts @@ -404,7 +404,7 @@ function transformInterfacesToTypes(tsAst: ts.SourceFile, str: MagicString, astO ); if (node.heritageClauses?.length) { - const extendsStart = str.original.indexOf('extends', node.getStart() + astOffset); + const extendsStart = node.heritageClauses[0].getStart() + astOffset; str.overwrite(extendsStart, extendsStart + 'extends'.length, '='); const extendsList = node.heritageClauses[0].types; diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx index e5807f4a2..8ba2848ea 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx +++ b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/expected.tsx @@ -18,6 +18,9 @@ function render() { } type Bar3 = Bar1 & Bar2 & { c: false; + } + type Bar4 = Bar1 & Bar2 & { + c: false; } let bar: Bar3; ; diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte index 23a066d79..9c0c4c85a 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte +++ b/packages/svelte2tsx/test/svelte2tsx/samples/transforms-interfaces-dts/input.svelte @@ -10,5 +10,8 @@ interface Bar3 extends Bar1, Bar2 { c: false; } + interface Bar4 extends Bar1, Bar2 { + c: false; + } export let bar: Bar3;