diff --git a/.changeset/olive-pandas-trade.md b/.changeset/olive-pandas-trade.md new file mode 100644 index 0000000000..bef36a3075 --- /dev/null +++ b/.changeset/olive-pandas-trade.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: allow using typescript in `customElement.extend` option diff --git a/documentation/docs/07-misc/04-custom-elements.md b/documentation/docs/07-misc/04-custom-elements.md index a8e0c81763..7e6a17b947 100644 --- a/documentation/docs/07-misc/04-custom-elements.md +++ b/documentation/docs/07-misc/04-custom-elements.md @@ -114,6 +114,8 @@ When constructing a custom element, you can tailor several aspects by defining ` ... ``` +> [!NOTE] While Typescript is supported in the `extend` function, it is subject to limitations: you need to set `lang="ts"` on one of the scripts AND you can only use [erasable syntax](https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly) in it. They are not processed by script preprocessors. + ## Caveats and limitations Custom elements can be a useful way to package components for consumption in a non-Svelte app, as they will work with vanilla HTML and JavaScript as well as [most frameworks](https://custom-elements-everywhere.com/). There are, however, some important differences to be aware of: diff --git a/packages/svelte/src/compiler/index.js b/packages/svelte/src/compiler/index.js index 42427dd9c4..756a88a824 100644 --- a/packages/svelte/src/compiler/index.js +++ b/packages/svelte/src/compiler/index.js @@ -43,6 +43,11 @@ export function compile(source, options) { instance: parsed.instance && remove_typescript_nodes(parsed.instance), module: parsed.module && remove_typescript_nodes(parsed.module) }; + if (combined_options.customElementOptions?.extend) { + combined_options.customElementOptions.extend = remove_typescript_nodes( + combined_options.customElementOptions?.extend + ); + } } const analysis = analyze_component(parsed, source, combined_options); diff --git a/packages/svelte/tests/runtime-browser/custom-elements-samples/extend-with-ts/_config.js b/packages/svelte/tests/runtime-browser/custom-elements-samples/extend-with-ts/_config.js new file mode 100644 index 0000000000..6502a08290 --- /dev/null +++ b/packages/svelte/tests/runtime-browser/custom-elements-samples/extend-with-ts/_config.js @@ -0,0 +1,19 @@ +import { test } from '../../assert'; +const tick = () => Promise.resolve(); + +export default test({ + async test({ assert, target }) { + target.innerHTML = ''; + await tick(); + /** @type {any} */ + const el = target.querySelector('custom-element'); + + assert.htmlEqual( + el.shadowRoot.innerHTML, + ` +

name: world

+ ` + ); + assert.equal(el.test, `test`); + } +}); diff --git a/packages/svelte/tests/runtime-browser/custom-elements-samples/extend-with-ts/main.svelte b/packages/svelte/tests/runtime-browser/custom-elements-samples/extend-with-ts/main.svelte new file mode 100644 index 0000000000..ddd2d4b61a --- /dev/null +++ b/packages/svelte/tests/runtime-browser/custom-elements-samples/extend-with-ts/main.svelte @@ -0,0 +1,14 @@ +{ + return class extends customClass{ + public test: string = "test"; + } + }, +}}/> + + + +

name: {name}

\ No newline at end of file