Closed riccardoscalco closed 2 years ago
Hi @riccardoscalco. Your question is more general, and not strictly related to hybrids, but to defining custom elements for the TS. I suppose, that there is no one the best way to do that, but I can recommend looking for some examples. One of the time elements from GitHub produces following d.ts
file:
export default class LocalTimeElement extends ExtendedTimeElement {
attributeChangedCallback(attrName: string, oldValue: string, newValue: string): void;
getFormattedDate(): string | undefined;
}
declare global {
interface Window {
LocalTimeElement: typeof LocalTimeElement;
}
interface HTMLElementTagNameMap {
'local-time': LocalTimeElement;
}
}
The above definition assumes, that this custom element is also registered in window.LocalTimeElement
. For proper recongnision with calls like document.createElement("local-time")
they put a tag name into the special HTMLElementTagNameMap
.
For the component built with hybrids, follow typescript guides for putting properties into the class, and create something like this:
class MyElement extends HTMLElement {
propOne: string;
propTwo: string;
}
declare global {
interface Window {
MyElement: typeof MyElement; // if you register your element in global scope
}
interface HTMLElementTagNameMap {
'my-element': LocalTimeElement;
}
}
There is also a tool https://github.com/runem/web-component-analyzer, which describes how you can add comments/metadata for better IDE completion.
I'm not sure, but it might be required to add a module
statement wrapper, as you expose it as an npm module:
declare module "@nextbitlabs/trend-line" {
...
}
For testing the best way is to set up a simple project, which uses TS and import your module by the relative path from the disk npm i ../trend-line
to check if d.ts
is correct.
Thanks for the precious suggestions, I give it a try!
Share your result when it will be ready :)
An update: I managed to automatically generate file index.d.ts
from a slightly modified version of the example in the docs. Note that I used import
from URL and plain JS similarly to the mentioned web-component I am working on.
File index.ts
is the following:
// @ts-ignore
import { define, html } from 'https://cdn.skypack.dev/hybrids@6';
function increaseCount(host) {
host.count += 1;
}
export const SimpleCounter = {
count: 0,
render: ({ count }) => html`
<button onclick="${increaseCount}">
Count: ${count}
</button>
`,
};
define('simple-counter', SimpleCounter);
The automatically generated index.d.ts
is:
export declare const SimpleCounter: {
count: number;
render: ({ count }: {
count: any;
}) => any;
};
I am not sure this index.d.ts
is useful at all.
Your automatically generated index.d.ts
won't be useful for code completion. It defines the hybrids definition, but users of your library interact with the custom element. You need an interface of your properties and extend global HTMLElementTagNameMap
to allow the TS server to find the definition when using document.createElement("my-element")
APIs.
Try to follow what I wrote in the last comments.
Feel free to re-open if you need more help with the subject.
Hi, recently I wrote a web component with hybrids. The package score in skypack.dev shows that TypeScript Types are missing in the package.
I am very new to TypeScript and I do not know exactly how to create the
index.d.ts
file for the web component. I found this page in hybrids docs, where there is an example of how to use TypeScript with hybrids.However, I prefer to keep the code in plain JS and create the file
index.d.ts
for the user-base that works with TypeScript.Could you please provide an example of the file
index.d.ts
related to a web component created with hybrids? Thanks in advance.