Reputation: 105
about my setup:
I'm having a bigger project which is implemented only using vanilla javascript in combination with the LitHTML library for writing web components. it works quite well. In my solution i have the checkJS flag enabled and i'm using JSDoc to get type safety, so the code is pretty clean. The editor we use is VScode and i'm already using the Lit, lit-html and lit-plugin plugin.
first problem:
now, you can use static get properties() {...}
to define the type of all your supported attributes for a webcomponent. but, the only types supported are: string, number, bool, array, object. I really want to know a solution where i can specify more complex types, and my type checking gives me a proper error if the provided variable has a different type
e.g. something like
static get properties() {
return {
user: { type: UserModel[], reflect: true }
}
}
should result in this line giving red underline in the editor window:
<my-component .users="${/** @type {SomeOtherModel[]} */ (models)}"></my-component>
maybe using JSDoc as normal Javascript wouldn't even support the idea of having generic arrays or so.
second problem:
the whole topic is even worse for events. in case of events, the event argument always becomes an implicit any, so no type checking at all. so in order to preserve type safety a simple line like this
<my-component @my-event"=${e=>console.log(e)}"></my-component>
would need to turn into this, when i enable noImplicitAny - which i really want to do!
<my-component @my-event="${/** @param {CustomEvent<ResultType>} */ e => console.log(e)}"></my-component>
and as long as er need to do that whenever i bind an event, native or custom, my fellow developers would probably punch me.
i would love to see a solution, a plugin, a JSDoc tag, a library, or maybe even custom javascript code to extend the LitElement class to finally have proper and solid type checking on the level of custom components
Upvotes: 0
Views: 783
Reputation: 105
so, i found the reason why it seems nobody implemented this until now. apparently the reason lies within typescript, which is used for type checking.
apparently typescript itself doesn't have an API for comparing types, until those two tickets get an implementation
https://github.com/Microsoft/TypeScript/issues/9879
https://github.com/Microsoft/TypeScript/issues/29432
for my own undestanding, which is hopefully correct, typescript itself doesn't devliver complex types. what it has is what you get when you run the typeof command: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
so if you evaluate a function like
<my-element .my-attribute=${target.myProperty}"></my-element>
you could read the definition of the .my-attribute from JSDoc comments or from the file itself, and with that you could even have a complex type, there is an NPM package doing exactly that for you. "web-component-analyzer"
but, the tricky part is getting the type of what's in the JS string interpolation.
now i don't know how exactly this even works, but apparently they use some kind of typescript API to get the type associated to the expression in the interpolation. But this type will not get some kind of "ComplexObject" it will always have one of the simple types described above.
so unless nobody finds some kind of super-hacky way to hack into the vscode type definitions and get's the type of this specific token i fear there's nothing we can do but wait.
Upvotes: -1