Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: move svelteHTML to load the correct svelte/element #9070

Merged
merged 8 commits into from Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slimy-dingos-call.md
@@ -0,0 +1,5 @@
---
'svelte': minor
---

feat: move `svelteHTML` from language-tools into core to load the correct `svelte/element` types
18 changes: 18 additions & 0 deletions documentation/docs/05-misc/03-typescript.md
Expand Up @@ -140,6 +140,24 @@ declare namespace svelteHTML {

Then make sure that `d.ts` file is referenced in your `tsconfig.json`. If it reads something like `"include": ["src/**/*"]` and your `d.ts` file is inside `src`, it should work. You may need to reload for the changes to take effect.

Since Svelte version 4.2 / `svelte-check` version 3.5 / VS Code extension version 107.10.0 you can also declare the typings by augmenting the the `svelte/elements` module like this:

```js
/// file: additional-svelte-typings.d.ts
import { HTMLButtonAttributes } from 'svelte/elements'

declare module 'svelte/elements' {
export interface SvelteHTMLElements {
'custom-button': HTMLButtonAttributes;
}

// allows for more granular control over what element to add the typings to
export interface HTMLButtonAttributes {
'veryexperimentalattribute'?: string;
}
}
```

## Experimental advanced typings

A few features are missing from taking full advantage of TypeScript in more advanced use cases like typing that a component implements a certain interface, explicitly typing slots, or using generics. These things are possible using experimental advanced type capabilities. See [this RFC](https://github.com/dummdidumm/rfcs/blob/ts-typedefs-within-svelte-components/text/ts-typing-props-slots-events.md) for more information on how to make use of them.
Expand Down
1 change: 1 addition & 0 deletions packages/svelte/package.json
Expand Up @@ -19,6 +19,7 @@
"motion.d.ts",
"action.d.ts",
"elements.d.ts",
"svelte-html.d.ts",
"README.md"
],
"exports": {
Expand Down
252 changes: 252 additions & 0 deletions packages/svelte/svelte-html.d.ts
@@ -0,0 +1,252 @@
/// <reference lib="dom" />
jasonlyu123 marked this conversation as resolved.
Show resolved Hide resolved
// This file is deliberately not exposed through the exports map.
// It's meant to be loaded directly by the Svelte language server
/* eslint-disable @typescript-eslint/no-empty-interface */

import * as svelteElements from './elements.js';

/**
* @internal do not use
*/
type HTMLProps<Property extends string, Override> = Omit<
import('./elements.js').SvelteHTMLElements[Property],
keyof Override
> &
Override;

declare global {
/**
* This namespace does not exist in the runtime, it is only used for typings
*/
namespace svelteHTML {
// Every namespace eligible for use needs to implement the following two functions
/**
* @internal do not use
*/
function mapElementTag<K extends keyof ElementTagNameMap>(tag: K): ElementTagNameMap[K];
function mapElementTag<K extends keyof SVGElementTagNameMap>(tag: K): SVGElementTagNameMap[K];
function mapElementTag(tag: any): any; // needs to be any because used in context of <svelte:element>

/**
* @internal do not use
*/
function createElement<Elements extends IntrinsicElements, Key extends keyof Elements>(
// "undefined | null" because of <svelte:element>
element: Key | undefined | null,
attrs: string extends Key ? svelteElements.HTMLAttributes<any> : Elements[Key]
): Key extends keyof ElementTagNameMap
? ElementTagNameMap[Key]
: Key extends keyof SVGElementTagNameMap
? SVGElementTagNameMap[Key]
: any;
function createElement<Elements extends IntrinsicElements, Key extends keyof Elements, T>(
// "undefined | null" because of <svelte:element>
element: Key | undefined | null,
attrsEnhancers: T,
attrs: (string extends Key ? svelteElements.HTMLAttributes<any> : Elements[Key]) & T
): Key extends keyof ElementTagNameMap
? ElementTagNameMap[Key]
: Key extends keyof SVGElementTagNameMap
? SVGElementTagNameMap[Key]
: any;

// For backwards-compatibility and ease-of-use, in case someone enhanced the typings from import('svelte/elements').HTMLAttributes/SVGAttributes
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface HTMLAttributes<T extends EventTarget = any> {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface SVGAttributes<T extends EventTarget = any> {}

/**
* Avoid using this interface directly. Instead use the `SvelteHTMLElements` interface exported by `svelte/elements`
* This should only be used if you need to extend the interface with custom elements
*/
interface IntrinsicElements extends svelteElements.SvelteHTMLElements {
a: HTMLProps<'a', HTMLAttributes>;
abbr: HTMLProps<'abbr', HTMLAttributes>;
address: HTMLProps<'address', HTMLAttributes>;
area: HTMLProps<'area', HTMLAttributes>;
article: HTMLProps<'article', HTMLAttributes>;
aside: HTMLProps<'aside', HTMLAttributes>;
audio: HTMLProps<'audio', HTMLAttributes>;
b: HTMLProps<'b', HTMLAttributes>;
base: HTMLProps<'base', HTMLAttributes>;
bdi: HTMLProps<'bdi', HTMLAttributes>;
bdo: HTMLProps<'bdo', HTMLAttributes>;
big: HTMLProps<'big', HTMLAttributes>;
blockquote: HTMLProps<'blockquote', HTMLAttributes>;
body: HTMLProps<'body', HTMLAttributes>;
br: HTMLProps<'br', HTMLAttributes>;
button: HTMLProps<'button', HTMLAttributes>;
canvas: HTMLProps<'canvas', HTMLAttributes>;
caption: HTMLProps<'caption', HTMLAttributes>;
cite: HTMLProps<'cite', HTMLAttributes>;
code: HTMLProps<'code', HTMLAttributes>;
col: HTMLProps<'col', HTMLAttributes>;
colgroup: HTMLProps<'colgroup', HTMLAttributes>;
data: HTMLProps<'data', HTMLAttributes>;
datalist: HTMLProps<'datalist', HTMLAttributes>;
dd: HTMLProps<'dd', HTMLAttributes>;
del: HTMLProps<'del', HTMLAttributes>;
details: HTMLProps<'details', HTMLAttributes>;
dfn: HTMLProps<'dfn', HTMLAttributes>;
dialog: HTMLProps<'dialog', HTMLAttributes>;
div: HTMLProps<'div', HTMLAttributes>;
dl: HTMLProps<'dl', HTMLAttributes>;
dt: HTMLProps<'dt', HTMLAttributes>;
em: HTMLProps<'em', HTMLAttributes>;
embed: HTMLProps<'embed', HTMLAttributes>;
fieldset: HTMLProps<'fieldset', HTMLAttributes>;
figcaption: HTMLProps<'figcaption', HTMLAttributes>;
figure: HTMLProps<'figure', HTMLAttributes>;
footer: HTMLProps<'footer', HTMLAttributes>;
form: HTMLProps<'form', HTMLAttributes>;
h1: HTMLProps<'h1', HTMLAttributes>;
h2: HTMLProps<'h2', HTMLAttributes>;
h3: HTMLProps<'h3', HTMLAttributes>;
h4: HTMLProps<'h4', HTMLAttributes>;
h5: HTMLProps<'h5', HTMLAttributes>;
h6: HTMLProps<'h6', HTMLAttributes>;
head: HTMLProps<'head', HTMLAttributes>;
header: HTMLProps<'header', HTMLAttributes>;
hgroup: HTMLProps<'hgroup', HTMLAttributes>;
hr: HTMLProps<'hr', HTMLAttributes>;
html: HTMLProps<'html', HTMLAttributes>;
i: HTMLProps<'i', HTMLAttributes>;
iframe: HTMLProps<'iframe', HTMLAttributes>;
img: HTMLProps<'img', HTMLAttributes>;
input: HTMLProps<'input', HTMLAttributes>;
ins: HTMLProps<'ins', HTMLAttributes>;
kbd: HTMLProps<'kbd', HTMLAttributes>;
keygen: HTMLProps<'keygen', HTMLAttributes>;
label: HTMLProps<'label', HTMLAttributes>;
legend: HTMLProps<'legend', HTMLAttributes>;
li: HTMLProps<'li', HTMLAttributes>;
link: HTMLProps<'link', HTMLAttributes>;
main: HTMLProps<'main', HTMLAttributes>;
map: HTMLProps<'map', HTMLAttributes>;
mark: HTMLProps<'mark', HTMLAttributes>;
menu: HTMLProps<'menu', HTMLAttributes>;
menuitem: HTMLProps<'menuitem', HTMLAttributes>;
meta: HTMLProps<'meta', HTMLAttributes>;
meter: HTMLProps<'meter', HTMLAttributes>;
nav: HTMLProps<'nav', HTMLAttributes>;
noscript: HTMLProps<'noscript', HTMLAttributes>;
object: HTMLProps<'object', HTMLAttributes>;
ol: HTMLProps<'ol', HTMLAttributes>;
optgroup: HTMLProps<'optgroup', HTMLAttributes>;
option: HTMLProps<'option', HTMLAttributes>;
output: HTMLProps<'output', HTMLAttributes>;
p: HTMLProps<'p', HTMLAttributes>;
param: HTMLProps<'param', HTMLAttributes>;
picture: HTMLProps<'picture', HTMLAttributes>;
pre: HTMLProps<'pre', HTMLAttributes>;
progress: HTMLProps<'progress', HTMLAttributes>;
q: HTMLProps<'q', HTMLAttributes>;
rp: HTMLProps<'rp', HTMLAttributes>;
rt: HTMLProps<'rt', HTMLAttributes>;
ruby: HTMLProps<'ruby', HTMLAttributes>;
s: HTMLProps<'s', HTMLAttributes>;
samp: HTMLProps<'samp', HTMLAttributes>;
slot: HTMLProps<'slot', HTMLAttributes>;
script: HTMLProps<'script', HTMLAttributes>;
section: HTMLProps<'section', HTMLAttributes>;
select: HTMLProps<'select', HTMLAttributes>;
small: HTMLProps<'small', HTMLAttributes>;
source: HTMLProps<'source', HTMLAttributes>;
span: HTMLProps<'span', HTMLAttributes>;
strong: HTMLProps<'strong', HTMLAttributes>;
style: HTMLProps<'style', HTMLAttributes>;
sub: HTMLProps<'sub', HTMLAttributes>;
summary: HTMLProps<'summary', HTMLAttributes>;
sup: HTMLProps<'sup', HTMLAttributes>;
table: HTMLProps<'table', HTMLAttributes>;
template: HTMLProps<'template', HTMLAttributes>;
tbody: HTMLProps<'tbody', HTMLAttributes>;
td: HTMLProps<'td', HTMLAttributes>;
textarea: HTMLProps<'textarea', HTMLAttributes>;
tfoot: HTMLProps<'tfoot', HTMLAttributes>;
th: HTMLProps<'th', HTMLAttributes>;
thead: HTMLProps<'thead', HTMLAttributes>;
time: HTMLProps<'time', HTMLAttributes>;
title: HTMLProps<'title', HTMLAttributes>;
tr: HTMLProps<'tr', HTMLAttributes>;
track: HTMLProps<'track', HTMLAttributes>;
u: HTMLProps<'u', HTMLAttributes>;
ul: HTMLProps<'ul', HTMLAttributes>;
var: HTMLProps<'var', HTMLAttributes>;
video: HTMLProps<'video', HTMLAttributes>;
wbr: HTMLProps<'wbr', HTMLAttributes>;
webview: HTMLProps<'webview', HTMLAttributes>;
// SVG
svg: HTMLProps<'svg', SVGAttributes>;

animate: HTMLProps<'animate', SVGAttributes>;
animateMotion: HTMLProps<'animateMotion', SVGAttributes>;
animateTransform: HTMLProps<'animateTransform', SVGAttributes>;
circle: HTMLProps<'circle', SVGAttributes>;
clipPath: HTMLProps<'clipPath', SVGAttributes>;
defs: HTMLProps<'defs', SVGAttributes>;
desc: HTMLProps<'desc', SVGAttributes>;
ellipse: HTMLProps<'ellipse', SVGAttributes>;
feBlend: HTMLProps<'feBlend', SVGAttributes>;
feColorMatrix: HTMLProps<'feColorMatrix', SVGAttributes>;
feComponentTransfer: HTMLProps<'feComponentTransfer', SVGAttributes>;
feComposite: HTMLProps<'feComposite', SVGAttributes>;
feConvolveMatrix: HTMLProps<'feConvolveMatrix', SVGAttributes>;
feDiffuseLighting: HTMLProps<'feDiffuseLighting', SVGAttributes>;
feDisplacementMap: HTMLProps<'feDisplacementMap', SVGAttributes>;
feDistantLight: HTMLProps<'feDistantLight', SVGAttributes>;
feDropShadow: HTMLProps<'feDropShadow', SVGAttributes>;
feFlood: HTMLProps<'feFlood', SVGAttributes>;
feFuncA: HTMLProps<'feFuncA', SVGAttributes>;
feFuncB: HTMLProps<'feFuncB', SVGAttributes>;
feFuncG: HTMLProps<'feFuncG', SVGAttributes>;
feFuncR: HTMLProps<'feFuncR', SVGAttributes>;
feGaussianBlur: HTMLProps<'feGaussianBlur', SVGAttributes>;
feImage: HTMLProps<'feImage', SVGAttributes>;
feMerge: HTMLProps<'feMerge', SVGAttributes>;
feMergeNode: HTMLProps<'feMergeNode', SVGAttributes>;
feMorphology: HTMLProps<'feMorphology', SVGAttributes>;
feOffset: HTMLProps<'feOffset', SVGAttributes>;
fePointLight: HTMLProps<'fePointLight', SVGAttributes>;
feSpecularLighting: HTMLProps<'feSpecularLighting', SVGAttributes>;
feSpotLight: HTMLProps<'feSpotLight', SVGAttributes>;
feTile: HTMLProps<'feTile', SVGAttributes>;
feTurbulence: HTMLProps<'feTurbulence', SVGAttributes>;
filter: HTMLProps<'filter', SVGAttributes>;
foreignObject: HTMLProps<'foreignObject', SVGAttributes>;
g: HTMLProps<'g', SVGAttributes>;
image: HTMLProps<'image', SVGAttributes>;
line: HTMLProps<'line', SVGAttributes>;
linearGradient: HTMLProps<'linearGradient', SVGAttributes>;
marker: HTMLProps<'marker', SVGAttributes>;
mask: HTMLProps<'mask', SVGAttributes>;
metadata: HTMLProps<'metadata', SVGAttributes>;
mpath: HTMLProps<'mpath', SVGAttributes>;
path: HTMLProps<'path', SVGAttributes>;
pattern: HTMLProps<'pattern', SVGAttributes>;
polygon: HTMLProps<'polygon', SVGAttributes>;
polyline: HTMLProps<'polyline', SVGAttributes>;
radialGradient: HTMLProps<'radialGradient', SVGAttributes>;
rect: HTMLProps<'rect', SVGAttributes>;
stop: HTMLProps<'stop', SVGAttributes>;
switch: HTMLProps<'switch', SVGAttributes>;
symbol: HTMLProps<'symbol', SVGAttributes>;
text: HTMLProps<'text', SVGAttributes>;
textPath: HTMLProps<'textPath', SVGAttributes>;
tspan: HTMLProps<'tspan', SVGAttributes>;
use: HTMLProps<'use', SVGAttributes>;
view: HTMLProps<'view', SVGAttributes>;

// Svelte specific
'svelte:window': HTMLProps<'svelte:window', HTMLAttributes>;
'svelte:body': HTMLProps<'svelte:body', HTMLAttributes>;
'svelte:document': HTMLProps<'svelte:document', HTMLAttributes>;
'svelte:fragment': { slot?: string };
'svelte:options': HTMLProps<'svelte:options', HTMLAttributes>;
'svelte:head': { [name: string]: any };

[name: string]: { [name: string]: any };
}
}
}