diff --git a/.changeset/slimy-dingos-call.md b/.changeset/slimy-dingos-call.md new file mode 100644 index 0000000000..4ecb122ae2 --- /dev/null +++ b/.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 diff --git a/documentation/docs/05-misc/03-typescript.md b/documentation/docs/05-misc/03-typescript.md index d5772fa157..b88c6f5c9f 100644 --- a/documentation/docs/05-misc/03-typescript.md +++ b/documentation/docs/05-misc/03-typescript.md @@ -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. diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 8a294c6dff..cbc11b3da7 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -19,6 +19,7 @@ "motion.d.ts", "action.d.ts", "elements.d.ts", + "svelte-html.d.ts", "README.md" ], "exports": { diff --git a/packages/svelte/svelte-html.d.ts b/packages/svelte/svelte-html.d.ts new file mode 100644 index 0000000000..3547ad0d33 --- /dev/null +++ b/packages/svelte/svelte-html.d.ts @@ -0,0 +1,252 @@ +/// +// 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 = 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(tag: K): ElementTagNameMap[K]; + function mapElementTag(tag: K): SVGElementTagNameMap[K]; + function mapElementTag(tag: any): any; // needs to be any because used in context of + + /** + * @internal do not use + */ + function createElement( + // "undefined | null" because of + element: Key | undefined | null, + attrs: string extends Key ? svelteElements.HTMLAttributes : Elements[Key] + ): Key extends keyof ElementTagNameMap + ? ElementTagNameMap[Key] + : Key extends keyof SVGElementTagNameMap + ? SVGElementTagNameMap[Key] + : any; + function createElement( + // "undefined | null" because of + element: Key | undefined | null, + attrsEnhancers: T, + attrs: (string extends Key ? svelteElements.HTMLAttributes : 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 {} + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface SVGAttributes {} + + /** + * 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 }; + } + } +}