Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/olive-pandas-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: allow using typescript in `customElement.extend` option
2 changes: 2 additions & 0 deletions documentation/docs/07-misc/04-custom-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 is subject to the same limitations of the script tags: 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.

## 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:
Expand Down
5 changes: 5 additions & 0 deletions packages/svelte/src/compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { test } from '../../assert';
const tick = () => Promise.resolve();

export default test({
async test({ assert, target }) {
target.innerHTML = '<custom-element name="world"></custom-element>';
await tick();
/** @type {any} */
const el = target.querySelector('custom-element');

assert.htmlEqual(
el.shadowRoot.innerHTML,
`
<p>name: world</p>
`
);
assert.equal(el.test, `test`);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<svelte:options customElement={{
tag: "custom-element",
extend: (customClass)=>{
return class extends customClass{
public test: string = "test";
}
},
}}/>

<script lang="ts">
let { name } = $props();
</script>

<p>name: {name}</p>