Exploring the process of extending Shoelace web components with Typescript using Lit

Once I extended the <sl-button> component in Lit, I realized that TypeScript was not catching errors for incorrect attributes being passed. For instance, in the code snippet provided below, when I use <sl-button> with an incorrect attribute, TypeScript correctly displays an error. However, if I use <my-button> with a wrong attribute, TypeScript does not show any errors.

import SlButton from '@shoelace-style/shoelace/dist/components/button/button.js';
import {html} from 'lit';
import {customElement} from 'lit/decorators.js';

@customElement('my-button')
export default class MyButton extends SlButton {
  constructor() {
    super();
  }
}

export const Demo = () =>
  html`
    <my-button size="not-exists">Click here!</my-button> // shows no error on "size"
    <sl-button size="not-exists">Click here!</sl-button> // shows error on "size"
  `;

declare global {
  interface HTMLElementTagNameMap {
    'my-button': MyButton;
  }
}

Answer №1

It seems like everything is functioning correctly as intended. From what I gather, the issue you're encountering doesn't seem to be a TypeScript error, as TypeScript does not concern itself with HTML attributes; rather, it pertains to code completion in your editor.

My suspicion is that you are working with VS Code with customized data provided by Shoelace. This data informs VS Code about Shoelace elements that are registered. By accessing

dist/vscode.html-custom-data.json
, you can view each tag along with a compilation of available attributes.

If you are extending and renaming Shoelace elements, you will need to supply your own personalized data to VS Code.


Here are a couple points to consider:

Firstly, when you import components/button/button.js, you are essentially registering a Shoelace button. To clarify, your code registers both <sl-button> and <my-button> due to registration occurring upon import.

Secondly, it's worth noting that renaming Shoelace components is not recommended. Many functionalities rely on specific tag names, for instance, <sl-menu> anticipates child elements to be <sl-menu-item>. Similarly, <sl-tab-group> expects children of <sl-tab> and <sl-tab-panel>. Altering these names may result in unexpected complications.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting Problem in Angular 6: Difficulty in presenting data using *ngFor directive (data remains invisible)

I came across a dataset that resembles the following: Within my app.component.html, I have written this code snippet: <ul> <li *ngFor="let data of myData">{{data.id}}</li> </ul> However, when I execute this code, it only displa ...

Utilizing a setup module for configuration purposes

In the process of developing my angular application, I have integrated several external modules to enhance its functionality. One crucial aspect of my final application is the configuration classes that store important values like URLs and message keys us ...

Encountering a console error in a TypeScript Express app when using MUI and Preact: "Unexpected prop `children` passed to `InnerThemeProvider`, was expecting a ReactNode."

I'm working on integrating MUI with a Preact app. In VSCode, everything seems to be set up correctly, but when I try to view it in the browser, nothing renders and I get this console error: react-jsx-runtime.development.js:87 Warning: Failed prop type ...

An issue arises when trying to utilize meta tags in Nuxtjs while incorporating TypeScript into the

When working with Nuxtjs, I encountered an issue regarding my permissionKeys on the page and checking user access in the middleware. Everything runs smoothly when my script language is set to js, but errors arise when set to lang="ts". I tried to find a s ...

Using the expect statement within a Protractor if-else block

My script involves an if-else condition to compare expected and actual values. If they do not match, it should go to the else block and print "StepFailed". However, it always executes the if block and the output is "step passed" even when expected does not ...

Stop extra properties from being added to the return type of a callback function in TypeScript

Imagine having an interface called Foo and a function named bar that accepts a callback returning a Foo. interface Foo { foo: string; } function bar(callback: () => Foo): Foo { return callback(); } Upon calling this function, if additional pr ...

Exploring async componentDidMount testing using Jest and Enzyme with React

angular:12.4.0 mocha: "8.1.2" puppeteer: 6.6.0 babel: 7.3.1 sample code: class Example extends Angular.Component<undefined,undefined>{ test:number; async componentWillMount() { this.test = 50; let jest = await import('jest&apos ...

Resolving search box setup problem in PrimeNG dataView

I am working on integrating p-dataView with Angular 5 but encountering an error Cannot read property 'split' of undefined at DataView.filter Despite checking the documentation, I have been unable to find a solution to this issue. It seems lik ...

What is the best way to retrieve data in my client component without risking exposing my API key to unauthorized users?

To retrieve information, I plan to use pagination in order to specify a particular page number within the API URL and fetch additional data by updating the value of page. The process of fetching data in my server component is as follows: // fetchData.tsx ...

What is the purpose of specifying an 'any' return type in TypeScript?

As an example: function retrieveUserInformation(input: any): any { return input } It may seem unnecessary to declare that "any data type can be returned". Is there a specific reason for this? ...

Create an asynchronous method within an object-oriented programming (OOP) class

Presenting my Activity class. export class Activity { _name: string _goIn: boolean constructor(name: string) { this._name = name; this._goIn = false; } isGoIn() { return this._goIn; } setGoIn() { // instructions to asyn ...

Transitioning an AngularJS factory to TypeScript

I'm currently in the process of transitioning an AngularJS application to Angular and one of the challenges I've encountered is converting my JavaScript code to TypeScript. While I've been successful with components and services, factories h ...

The external typing file encounters an issue when trying to locate the relative path to its own index.d.ts file

While working on my project and using react-color as a dependency, I encountered an issue with the tsc import failing. The error message displayed: node_modules/@types/react-color/lib/components/sketch/Sketch.d.ts(2,41): error TS2307: Cannot find module & ...

Error encountered: The term 'interface' is a restricted keyword

I am in the process of developing a NodeJS and MongoDB library for performing CRUD operations on APIs. My goal is to establish an interface with Typescript that includes the url and database name, structured as follows: However, I am encountering this par ...

A guide on how to implement promise return in redux actions for react native applications

I'm using redux to handle location data and I need to retrieve it when necessary. Once the location is saved to the state in redux, I want to return a promise because I require that data for my screen. Here are my actions, reducers, store setup, and ...

Execute multiple observables concurrently, without any delay, for every element within a given list

I've been attempting to utilize mergeMap in order to solve this particular issue, but I'm uncertain if my approach is correct. Within my code, there exists a method named getNumbers(), which makes an HTTP request and returns a list of numbers (O ...

Save JSON Tree data in the Database

Given a tree structure JSON, I am tasked with creating an API to insert all the data into a database at once. The organization entities can have multiple parents and children relationships. An example of the JSON data: { "org_name": "orga ...

Exploring the archives of PubNub within Angular5

I've been working on integrating PubNub history into my web app, but I'm currently only able to view it in the console. Here's what I have so far: pubnub.history( { channel: 'jChannel', reverse: false, ...

Cross-origin error triggered by using an external API within a ReactJS application

I'm facing a common CORS issue in my application while trying to call an API. The API I am attempting to access can be found here: https://github.com/nickypangers/passport-visa-api Below is the code snippet used for making the API call: const getVi ...

`The flaw in filtering logic - an analysis`

Looking to find matching records within two Lists. We have a List called allAnimals with attributes like animalId, and another List named domesticAnimals also containing animalId. The goal is to compare the two lists and create a new list where the anima ...