svelte
svelte copied to clipboard
[feat] add html typings
This adds typings for HTML elements and their attributes. It's supposed to be used by the new transformation in language-tools.
Open questions:
- should the event typings be
onclick: ...or"on:click": ...oronclick: string, "on:click": ...? The first option is how it was transformed/dealt with in language-tools previously. - where should this be exposed?
import { .. } from 'svelte'or sth likeimport { ... } from 'svelte/html'?
Before submitting the PR, please make sure you do the following
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] Prefix your PR title with
[feat],[fix],[chore], or[docs]. - [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.
Tests
- [ ] Run the tests with
npm testand lint the project withnpm run lint
Vote for on:event, if there aren't technical difficulties. And svelte/html. Also, we can probably consider https://github.com/sveltejs/language-tools/issues/684 if we bump the minimal typescript version in svelte 4?
agree with exporting from svelte/html instead of svelte.
what would user see whether we use onclick or on:click?
Right now the : is removed by language tools, so on:click becomes onclick for the purpose of typing.
The transformation is roughly this: <div onclick={foo} /> --> createElement('div', { "onclick": foo });
If we do the typings like on:click, we wouldn't need to remove the colon in language-tools.
Thought about the addition of : some more, I've also written down a roadmap towards the end goal, the new transformation (https://github.com/sveltejs/language-tools/issues/1552). I'm not sure anymore if we should use the colons since Svelte Native and Svelte NodeGUI both use the onX event typings. I'm not sure we can coordinate this bump in a way that works for users in a seamless way.
- should the event typings be
onclick: ...or"on:click": ...oronclick: string, "on:click": ...? The first option is how it was transformed/dealt with in language-tools previously.
Whichever one we go with, NativeScript events are unavoidably camelcase, and I think NodeGUI events can even lead with a capital letter (I can't remember). I know anything but all lowercase probably violates some policy in the DOM Level 0 Events spec, but if there's really no actual restriction on the Svelte side, it would really help out custom renderers if the event handlers were unrestrictive on casing. Beyond that, I think any format can work, but it's been such a long time since I worked on this that I'm afraid I can't remember whether on:click posed any more/less problems than onclick.
- where should this be exposed?
import { .. } from 'svelte'or sth likeimport { ... } from 'svelte/html'?
They seem to be module-based typings, rather than ambient (strictly speaking "script" typings) so they won't infect custom renderers with Web typings, right? If so, then anywhere is fine. If it's the only thing that's ever going to live insvelte/html and there'll never be a "svelte/native" or "svelte/nodegui" path in the npm package, then maybe just keep it as from "svelte".
See https://github.com/sveltejs/language-tools/pull/1549#issuecomment-1176045813, I lean more and more towards no doing on:X typings because of the ecosystem breakage it would mean. It sucks but I think we have to pay the price of suboptimal decisions earlier on here.
Edit: I think I revert my earlier decision and go with the on:X approach. Reasons:
- Fear of leaving people who enhanced the definitions behind: No problem as TypeScript allows us to transform these names (see https://github.com/sveltejs/language-tools/pull/1549#issuecomment-1176045813 for the code)
- Fear of breaking NodeGUI and SvelteNative: Not a big problem as we can add fallback any typings so people don't get an error
- Fear of breaking libraries: If they specify "this uses props from svelte2tsx" they export props "onclick" etc which are wrong anyway
I don't have a strong opinion about this although I leaned toward on:event. The template-literal redirect looks impressive. Do this mean we would use the on:event in here but have the helper function in svelte2tsx redirect the old style?
The helper function could be used to migrate enhancements by users on the old namespace by doing something like interface HTMLAttributes extends EventsWithColon<svelte.JSX.HTMLAttributes>, so this wouldn't break for them. We would keep the old JSX namespace around but with empty interfaces.
Just tried this out with the new transformation + the mentioned type transformation (onx -> on:x) for old JSX attributes - works like a charm! Marking this ready for review.
Thanks for checking so thoroughly! I adjusted the typings for bindings, the related PR on language-tools is https://github.com/sveltejs/language-tools/pull/1596
I'm a little uncomfortable having something called svelte/html also export types for <svelte:xxx> special elements and (to a lesser extent) directives like on:xxx and bind:xxx. Is there another name we can find for this that indicates that this isn't just for HTML types? svelte/template was the first thing I thought of, but I don't really like that. Are these types you're foreseeing anyone manually importing anywhere, or would it just be a language tools thing pretty much?
I also feel quite gross about having SvelteKit- and Sapper-specific types in the core Svelte repo. I assume this was done because it seemed like the least bad option? I don't think we have to worry about Sapper too much, but: There's no reasonably way to have the SvelteKit-specific types published in the SvelteKit package and for the language tools to pull in the types from both places?
The idea was to have one place where we can put these typings and the whole ecosystem can draw from them: language-tools mainly, but also package authors who may want to use these typings for their type definitions. Currently there's svelte2tsx usage in the wild because of that (svelte.JSX.HTMLAttributes mainly) and it feels weird that people have to import type definitions from some package whose primarily job is to work under the hood. Also it's harder to guess the impact of breaking changes in svelte2tsx if people keep using it. The next best place that isn't a separate package (which we could do, but also feels kind of weird, but I could be persuaded to) is therefore Svelte itself.
We could call it html-typings which would be more accorately describing what this does.
About kit-specific typing. Maybe we could use Module Augmentation in the kit to enhance the anchor attribute typing. And language server could load the fallback version if we detect the user using an old version of the kit.
// whatever the name it ends up with
declare module 'svelte/html-typings' {
interface HTMLAnchorAttributes {
'sveltekit:noscroll'?: true | undefined | null;
}
}
// tell ts this file is a module
export {}
html-types rather than typings would be better because that's what it will be exporting...
We decided on svelte/elements
For some reason this "breaks" components that defined it's own typing for value

https://github.com/sveltejs/svelte/blob/7e6acbece31fbd68e2c07e37f3c849c405eb6983/elements/index.d.ts#L796-L798
https://github.com/rgossiaux/svelte-headlessui/blob/master/src/lib/components/listbox/ListboxOption.svelte#L1-L27
TPassThroughProps<TSlotProps, TAsProp, "li">
Could you open a new issue at https://github.com/sveltejs/language-tools/issues with a code snippet reproducing the error? Thanks.